Make ThreadSystem onfork handlers threadsafe

This commit is contained in:
Sebastian Messmer 2015-11-07 00:11:12 -08:00
parent 236ea8d243
commit 47bd752a97
3 changed files with 10 additions and 4 deletions

View File

@ -12,7 +12,7 @@ namespace cpputils {
string result;
char buffer[1024];
while(fgets(buffer, sizeof(buffer), subprocessOutput) != NULL) {
while(fgets(buffer, sizeof(buffer), subprocessOutput) != nullptr) {
result += buffer;
}
@ -39,4 +39,4 @@ namespace cpputils {
}
return subprocess;
}
}
}

View File

@ -11,21 +11,23 @@ namespace cpputils {
return system;
}
ThreadSystem::ThreadSystem(): _runningThreads() {
ThreadSystem::ThreadSystem(): _runningThreads(), _mutex() {
//Stopping the thread before fork() (and then also restarting it in the parent thread after fork()) is important,
//because as a running thread it might hold locks or condition variables that won't play well when forked.
pthread_atfork(&ThreadSystem::_onBeforeFork, &ThreadSystem::_onAfterFork, &ThreadSystem::_onAfterFork);
}
ThreadSystem::Handle ThreadSystem::start(function<void()> loopIteration) {
boost::unique_lock<boost::mutex> lock(_mutex);
auto thread = _startThread(loopIteration);
_runningThreads.push_back(RunningThread{loopIteration, std::move(thread)});
return std::prev(_runningThreads.end());
}
void ThreadSystem::stop(Handle handle) {
boost::unique_lock<boost::mutex> lock(_mutex);
handle->thread.interrupt();
handle->thread.join();
handle->thread.join(); //TODO Can I release the lock before calling join()? Maybe I have to move the erase() line to earlier (inside the lock).
_runningThreads.erase(handle);
}
@ -38,6 +40,7 @@ namespace cpputils {
}
void ThreadSystem::_stopAllThreadsForRestart() {
_mutex.lock(); // Is unlocked in the after-fork handler. This way, the whole fork() is protected.
for (RunningThread &thread : _runningThreads) {
thread.thread.interrupt();
}
@ -50,6 +53,7 @@ namespace cpputils {
for (RunningThread &thread : _runningThreads) {
thread.thread = _startThread(thread.loopIteration);
}
_mutex.unlock(); // Was locked in the before-fork handler
}
boost::thread ThreadSystem::_startThread(function<void()> loopIteration) {

View File

@ -31,11 +31,13 @@ namespace cpputils {
static void _onBeforeFork();
static void _onAfterFork();
//TODO Rename to _doOnBeforeFork and _doAfterFork or similar, because they also handle locking _mutex for fork().
void _stopAllThreadsForRestart();
void _restartAllThreads();
boost::thread _startThread(std::function<void()> loopIteration);
std::list<RunningThread> _runningThreads; // std::list, because we give out iterators as handles
boost::mutex _mutex;
DISALLOW_COPY_AND_ASSIGN(ThreadSystem);
};