Hacker News new | ask | show | jobs
by bmalehorn 3589 days ago
The code is more complicated than it needs to be. It spawns N threads, then each thread forkexecs child processes. These threads communicate through an atomic int.

There is no need for threads. Just spawn background processes:

    echo 1 &
    echo 2 &
    wait
    echo 3 &
    wait
    echo 4 &
    ...
The key is that the wait() system call will hang until any child process finishes.
1 comments

I doubt that will make it measurable more efficient. Threads are cheap.
My point wasn't optimization. Just that the author was making it more complicated than was needed.

It's like discovering that "ls" is spawning 5 threads for internal communication.

In a language with good threading support, internal threads are typically making things easier rather than harder. I tend to spawn lots of threads in Rust just because I can and it simplifies the code a lot over having to do some async callback mess.

In particular there is no sane way to async waitpid() on POSIX.

pselect / self-pipe / etc. on SIGCHLD, and on receipt of SIGCHLD, loop through all known child processes with wait(WNOHANG).

... I'm not sure I can disagree with "no sane way".

The only thing you can do from a signal handler is flipping a static and only one signal handler can be set. Good luck making this reusable.

In fact, I challenge you to solve the problem "spawn process; waitpid for 15 seconds; otherwise kill hard" in Rust (or C++ if you feel like) on POSIX once with threads and once without threads by sticking to what's permitted in the standard and so that multiple processes can be waited for.

Then also measure CPU impact :)

> The only thing you can do from a signal handler is flipping a static and only one signal handler can be set.

This is false, you can call any async signal safe function. Incidentally write is one of them.

Another trick is the close-on-exit pipe.

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.