Andrew Loomis
Andrew Loomis

Reputation: 135

Using shared_ptr to end multithreaded loops on interrupt

So I'm trying to gracefully shut down several threads in loops when I interrupt a program (with SIGINT). Right now I use a callback that changes the state of a shared_ptr (which was copied to each thread) to indicate to all the other threads that it's time to break the loop (the threads check the state of the shared_ptr each iteration). This works, but I was wondering if it was "good" programming practice?

Upvotes: 0

Views: 151

Answers (1)

eerorika
eerorika

Reputation: 238401

No, it is not guaranteed to be safe to modify a shared pointer in a signal handler. Nor is modification of a shared pointer safe (except copying which is safe despite modifying the internal state) across multiple threads

What would be safe is to use volatile std::sig_atomic_t as a flag and modify it in the signal handler. However, sig_atomic_t does not guarantee synchronisation to other threads than the one that handles the signal.

If you can rely on std::atomic<bool> being lock free (which isn't guaranteed by the standard), it would also be valid for modification in a signal handler, as well as guaranteeing thread synchronisation.

Otherwise, you could use a thread local volatile std::sig_atomic_t for the signal handler, and once change is detected in one thread, broadcast the information to other threads using a secondary thread syncronisation method (atomic, condition variable, etc.).

Another approach: you could have one thread simply waiting for the signal (no need for a sig-atomic flag), and once received, proceed with the thread synchronised broadcasting (same second phase as in previous suggestion). Note that the signal would have to be masked for other threads so that it is given for the waiting thread to handle. However, there is no good API for waiting for a signal in standard C++. There is sigwait in the POSIX standard, if you can rely on that.

Upvotes: 1

Related Questions