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