Hacker News new | ask | show | jobs
by cryptonector 1414 days ago
> it's not rocket science to handle it in a sane fashion even in a multi-threaded application

It's not, though you need to be careful if you want to exit cleanly -- you can't just exit() or _exit(). You have to get all the threads to exit, and that requires a global volatile sig_atomic_t flag and some way to signal all threads that might be sleeping in event loops or what have you.

2 comments

Sure you can just exit(), you just have to be sure that all your on-disk state changes are atomic. Which you should make sure of anyways.
A separate thread with sigwait() may be easier. Though I must admit, I've rarely had to do that manually, as I'm usually using a language or framework that gives an easier way to get notified about signals (e.g. Python KeyboardInterrupt or listeners in Boost ASIO or libuv). Aside from saving some boilerplate, those also emulate equivalent signals in Windows.

Threads waiting on event loops is exactly what you want on shutdown: that's what you use to notify them to exit.

I never use sigwait() or sigsuspend() -- I just have signal handlers that write a byte (e.g., the signal number) into a pipe, and maybe they set a global volatile sig_atomic_t variable. DJB calls this a "self-pipe". A self-pipe turns signals into I/O events that select/poll/epoll/event ports/kqueue/io_ring/whatever can handle like any other events.

At exit time I just make sure every thread can get an event. The main thread can pthread_cond_wait() for all the other threads to exit, waiting for the count of them to fall to zero.

Ah self pipe is a good idea, I suspect that's what those async frameworks are doing under the hood.