5 ms·
If your service manager cannot track forked process, that would be quite an issue anyway "Daemonization" is nothing but fork + exec (and exit from the parent)
by JackSlateur 2y ago
If your service manager cannot track forked process, that would be quite an issue anyway
"Daemonization" is nothing but fork + exec (and exit from the parent)
From the service manager, there should be few distinctions between this and, say, pgsql forking to handle connections. In both cases, I expect all child processes to be tracked.
And please do not tell me the "health check" part : having the main process alive is a broken health check, just like having a server powered-on is a far from enough
- kbolino 2y agoThere is one very important distinction. If pgsql forks to handle connections, the PPID of the child processes points back to the "main" pgsql process, which is still around. Whereas, traditionally, if a wannabe daemon forks and exits, the PPID of its now orphaned child reverts to 1.
- zokier 2y agoafaik you need cgroups if you want to accurately track a process tree regardless of what silly tricks the processes might be try to escape
- thwarted 2y agoOr prctl and PR_SET_CHILD_SUBREAPER are potentially useful for that.
- kazinator 2y agoSo, all-round agreement that you need Linux extensions to fix legacy Unix situations that can be avoided by not forking grandchildren and using pidfiles and whatnot.
- thwarted 2y agoYes, as time goes on, new features are added, and some are meant to address deficiencies that were unanticipated at the time and the limitations of the earlier designs are discovered.
- thayne 2y agoHow does that help? Setting that on the init process is pointless, since init already has the reaping behavior, and it when a process is reparented it doesn't give init any information about what the parent was when it is reparented. Setting it on the service process isn't helpful either, since the fored process will get reparented to init after the forking process dies since a dead process can't reap it.
- kbolino 2y agoWith subreaping as the only additional mechanism available, init would have to fork itself first and then keep that child running until all its descendants are done. Basically, every service would have a supervisor process (controlled by init) which roots a tree of all its other processes.
- thwarted 2y agoSetting a process as the reaper means descendent processes are reparented to the reaper, which has to call wait like pid 1 does in order to collect the process's info and remove the zombie. This changes the default behavior where they are reparented to pid 1. You don't set this on pid 1 because, as you point out, pid 1 is already the reaper of last resort. You don't set this on the service process either; it is set on a process manager that isn't pid 1, so that process can monitor and collect info about its subtree of processes.
- thayne 2y agoAnd not even cgroups are enough if the process has write access to another cgroup (for example, because it is root)
- kazinator 2y agoFrom the service manager point of view, a daemonizing program is a headache. The program that the service manager thinks is starting immediately quits, and it's the grandchild (or even great grandchild) that's actually the payload service. Because the parent quit, the grandchild becomes reparented to the init daemon; it is not a child of the service manager. The service manager has no idea what the process ID of the service is. If the self-daemonizing program writes its PID to a pidfile, and the service manaager is configured to know what that is and look for it, it can be obtained that way. Not being the parent of the process, the service manager doesn't get notified when that process terminates. It has to use hacks to poll for it; like kill the PID with signal 0 to check liveness, and pray that the PID isn't recycled. If you're writing a deamon program, make sure daemonization is optional, favoring opt-in over opt-out.
- JackSlateur 2y agocgroup is the only way to track a process and its children, as far as I know Either you use cgroup (in which case, neither the parent pid nor pidfile nor even the process ID are useful), either you do not (in which case, you leak processes) Stopping a service means, in the end, killing all processes in the associated cgroup.