Hacker News new | ask | show | jobs
by geofft 3582 days ago
Here's a sound implementation with signals using only the Rust standard library and POSIX, no threads:

https://play.rust-lang.org/?gist=ba4802a59f462cb8bce0c1bac92...

It would be significantly simpler with sigwaitinfo() if you didn't care to do a real select loop, but I assume most programs want a real select (or poll/epoll/whatever) loop.

1 comments

Which proves my point. It's messy, inefficient and now you wrote code which is not composable as you have a global (and the only) signal handler.
I don't think it's less efficient than threads (but someone should test it!). It scales better.

It's not composable, but it's not impossible to work around that if you can assume non-POSIX. Platforms with kqueue just get this right because kqueue can wait for processes. Linux will let you use a different signal to alert for process completion, so pick one of the realtime signals (which is its own game of global namespaces, but hey), and library code that uses SIGCHLD won't be affected. So that's Linux, OS X, and the BSDs. I don't know of a good workaround for Solaris.

A POSIX-compliant way that makes this more composable is to make a single, dummy process to be a process group, setpgid() all your actual children into that process group, and have that process spend its time doing waitpid(0, WNOHANG) and sending you notifications over a pipe or something. That is higher overhead, but my guess is that scales better for many child processes (O(1) extra processes vs. O(n) extra threads).

It's less efficient if the "master" has to select over multiple things. Eg: waiting for children to finish, do some IO with them etc.

In that case you are pretty much limited to polling on the thing (unless apparently you use kqueue, did not know you can wait on process events).