初学 go ,最近在阅读 wireguard-go 的代码,看到其 daemonize 相关的代码,其中有如下代码段(去掉无关代码):
path, err := os.Executable()
if err != nil {
fmt.Printf("Failed to determine executable: %v\n", err)
os.Exit(-1)
}
process, err := os.StartProcess(
path,
os.Args,
attr,
)
if err != nil {
fmt.Printf("Failed to daemonize: %v\n", err)
os.Exit(-1)
}
fmt.Printf("chile process pid is %v\n", process.Pid)
err = process.Release()
if err != nil {
fmt.Printf("release process failed %v\n", err)
}
其中 process.Release()
究竟 Release 了什么,注释中提到的是:"Release releases any resources associated with the Process p, rendering it unusable in the future." ,这其中resources
指的是什么?
github中也有相关的 Issues ,提到“ I've sent the PR that specifying Release's NOOP behavior on Unix.” 其中 "NOOP" 是什么意思? NO operation 什么都不做吗?
我简单试验了一下,如果父进程执行完创建进程后立刻退出了,不管是否进行 Release , 子进程都会被托管给 launchd 进程。
而如果父进程没有立即退出,进行了 Release ,这时候子进程的父进程就是创建他的进程如果子进程先退出,此时子进程就会变成一个僵尸进程。不进行 Release 的结果也是一样的。
我感到非常的混乱,Release 感觉像是什么都没有做一样,不知道我的感觉是否正确?
1
ho121 2023-06-02 10:27:59 +08:00
没写过 go ,不过大概猜测 Release 是回收子进程,防止僵尸进程的出现。建议看看僵尸进程的相关文章。
|
2
Jerry23333 OP 感谢您的回复,我起初也是觉得 Release 是防止出现僵尸进程的,但我测试了下 不管有没有 Release ,子进程退出以后都会变成僵尸进程,如 91566 。
```bash 91563 ttys000 0:00.01 ./main -t 91566 ttys000 0:00.00 <defunct> ``` |
3
ysc3839 2023-06-02 10:44:27 +08:00 via Android 1
在 Windows 下会关闭 Process Handle
|
4
flyqie 2023-06-02 10:45:58 +08:00 via Android
用完就释放是个好习惯。
你不能假定底层会做什么,但起码你可以把你能做的都给做了。 哪怕底层现在是 NOOP ,后期也可能会更改(况且还要考虑到跨平台),为了保证代码的可靠性,最好从一开始就把能做的都给做了,这样能避免很多问题。 在任何语言都是这样的。 有 gc 的话尽量(不是全部,那不是你应该做的)减少 gc 的工作,来优化性能,gc 适用的是普遍环境,某些特殊情况下 gc 做的优化可能并不咋地。 没有 gc 的话只能自己处理,总不能全在进程退出的时候由系统处理吧? |
5
Jerry23333 OP |
6
harrozze 2023-06-02 11:17:27 +08:00 1
@flyqie #4 C 语言入门的程序员可能会有这习惯,写好 malloc 就去在合适的地方放个 free 。从自带 gc 语言入门的,这方面意识可能不强,或者得是到后期考虑到优化和防漏才会逐步加强吧。
|
8
flyqie 2023-06-02 11:21:26 +08:00 via Android
|
9
PTLin 2023-06-02 17:48:21 +08:00
unix 下没有任何用,就是简单的把 pid 设置成了-1 ,然后清理了一下 Finalizer ,并且你不调用这个方法这个对象在 gc 回收的时候也会调用这个 Release
|