From a4a62f390a59845c7ab168fea17156b05b59799d Mon Sep 17 00:00:00 2001 From: Bart van Strien Date: Sun, 2 Jul 2017 15:27:58 +0200 Subject: [PATCH] Disable signal handling in threads (see issue #1042) I don't necessarily like having to do these extra calls whenever threads are spawned (and what happens to signals during the time signal delivery is disabled?) but it seems to fully fix os.execute. NOTE: Also disables signals when loading openal, as it or one of its backends spawns threads internally, and does not disable signals itself. --HG-- branch : minor --- src/modules/audio/openal/Audio.cpp | 9 +++++++++ src/modules/system/System.cpp | 26 -------------------------- src/modules/thread/sdl/Thread.cpp | 9 +++++++++ src/modules/thread/threads.cpp | 20 ++++++++++++++++++++ src/modules/thread/threads.h | 5 +++++ 5 files changed, 43 insertions(+), 26 deletions(-) diff --git a/src/modules/audio/openal/Audio.cpp b/src/modules/audio/openal/Audio.cpp index f9a9a897a..5126e9209 100644 --- a/src/modules/audio/openal/Audio.cpp +++ b/src/modules/audio/openal/Audio.cpp @@ -96,6 +96,11 @@ Audio::Audio() , poolThread(nullptr) , distanceModel(DISTANCE_INVERSE_CLAMPED) { +#if defined(LOVE_LINUX) + // Temporarly block signals, as the thread inherits this mask + love::thread::disableSignals(); +#endif + // Passing null for default device. device = alcOpenDevice(nullptr); @@ -116,6 +121,10 @@ Audio::Audio() if (!alcMakeContextCurrent(context) || alcGetError(device) != ALC_NO_ERROR) throw love::Exception("Could not make context current."); +#if defined(LOVE_LINUX) + love::thread::reenableSignals(); +#endif + #ifdef ALC_EXT_EFX initializeEFX(); diff --git a/src/modules/system/System.cpp b/src/modules/system/System.cpp index 9bfd361b4..2c330f2fb 100644 --- a/src/modules/system/System.cpp +++ b/src/modules/system/System.cpp @@ -42,20 +42,6 @@ #include #endif -#if defined(LOVE_LINUX) -static void sigchld_handler(int sig) -{ - // Because waitpid can set errno, we need to save it. - auto old = errno; - - // Reap whilst there are children waiting to be reaped. - while (waitpid(-1, nullptr, WNOHANG) > 0) - ; - - errno = old; -} -#endif - namespace love { namespace system @@ -63,18 +49,6 @@ namespace system System::System() { -#if defined(LOVE_LINUX) - // Enable automatic cleanup of zombie processes - // NOTE: We're using our own handler, instead of SA_NOCLDWAIT because the - // latter breaks wait, and thus os.execute. - // NOTE: This isn't perfect, due to multithreading our SIGCHLD can happen - // on a different thread than the one calling wait(), thus causing a race. - struct sigaction act = {0}; - sigemptyset(&act.sa_mask); - act.sa_handler = sigchld_handler; - act.sa_flags = SA_RESTART; - sigaction(SIGCHLD, &act, nullptr); -#endif } std::string System::getOS() const diff --git a/src/modules/thread/sdl/Thread.cpp b/src/modules/thread/sdl/Thread.cpp index d53fbeed9..db12a5e3f 100644 --- a/src/modules/thread/sdl/Thread.cpp +++ b/src/modules/thread/sdl/Thread.cpp @@ -42,6 +42,11 @@ Thread::~Thread() bool Thread::start() { +#if defined(LOVE_LINUX) + // Temporarly block signals, as the thread inherits this mask + love::thread::disableSignals(); +#endif + Lock l(mutex); if (running) return false; @@ -49,6 +54,10 @@ bool Thread::start() SDL_WaitThread(thread, nullptr); thread = SDL_CreateThread(thread_runner, t->getThreadName(), this); running = (thread != nullptr); + +#if defined(LOVE_LINUX) + love::thread::reenableSignals(); +#endif return running; } diff --git a/src/modules/thread/threads.cpp b/src/modules/thread/threads.cpp index da42d0180..ace8b5d4d 100644 --- a/src/modules/thread/threads.cpp +++ b/src/modules/thread/threads.cpp @@ -20,6 +20,10 @@ #include "threads.h" +#if defined(LOVE_LINUX) +#include +#endif + namespace love { namespace thread @@ -153,5 +157,21 @@ Conditional *ConditionalRef::operator->() const return conditional; } +#if defined(LOVE_LINUX) +static sigset_t oldset; + +void disableSignals() +{ + sigset_t newset; + sigfillset(&newset); + pthread_sigmask(SIG_SETMASK, &newset, &oldset); +} + +void reenableSignals() +{ + pthread_sigmask(SIG_SETMASK, &oldset, nullptr); +} +#endif + } // thread } // love diff --git a/src/modules/thread/threads.h b/src/modules/thread/threads.h index 65ebc9934..21bc454d0 100644 --- a/src/modules/thread/threads.h +++ b/src/modules/thread/threads.h @@ -129,6 +129,11 @@ Mutex *newMutex(); Conditional *newConditional(); Thread *newThread(Threadable *t); +#if defined(LOVE_LINUX) +void disableSignals(); +void reenableSignals(); +#endif + } // thread } // love