4 ms·
waitpid(-1) in a program composed of libraries means that loop is stealing PIDs from other things that manage children within the same process and try to wait o
by the8472 2y ago
waitpid(-1) in a program composed of libraries means that loop is stealing PIDs from other things that manage children within the same process and try to wait on them by PID, which means they'll lose access to the exit status and can also lead to hangs due to pid recycling and then waiting on the wrong pid.
It can work in a self-contained program, but not in anything complicated.
For children specifically pidfds are more reliable. But that doesn't help with other signals.
- chubot 2y agoYes waitpid(-1) doesn't compose, but lots of things in the C world don't compose - using library A which uses say libuv, and one that uses libevent (two different event loops) - forking while holding locks - two libraries using two different thread pools -- concurrency policy is a global concern. (and this one isn't specific to C) FWIW the solution I use in a shell is simple - create a Waiter object that wraps waitpid(), and only code that has a reference to the waiter can do anything with processes. It's basically like making an event loop object and passing it around, rather than making it global. This is also an argument for libraries not doing I/O -- they should be pure. They should be parameterized by I/O, including starting threads, etc. I haven't ever wanted to use a library that starts processes behind my back
- thayne 2y ago> using library A which uses say libuv, and one that uses libevent (two different event loops) It's not ideal, but I don't see a reason this wouldn't work if you ran the two event loops on separate threads > forking while holding locks Yes. You can't use fork in a multi-threaded program, unless it is followed by an exec. Which is one reason forking is somewhat rare in modern code. > two libraries using two different thread pools -- concurrency policy is a global concern. That doesn't break the semantics of the program. > create a Waiter object that wraps waitpid(), and only code that has a reference to the waiter can do anything with processes. This doesn't help if you use a library that calls waitpid directly. This is actually probably more of a problem in non-c code, where the standard library likely to have an abstraction that calls waitpid on child processes. So handling SIGCHLD can interfere with other code waiting for a child to finish.