Index: lldb/include/lldb/Host/MainLoop.h =================================================================== --- lldb/include/lldb/Host/MainLoop.h +++ lldb/include/lldb/Host/MainLoop.h @@ -56,7 +56,7 @@ // handler. However, since the callback is not invoked synchronously, you // cannot use this mechanism to handle SIGSEGV and the like. SignalHandleUP RegisterSignal(int signo, const Callback &callback, - Status &error); + Status &error, void *callback_id = nullptr); Status Run() override; @@ -68,7 +68,7 @@ protected: void UnregisterReadObject(IOObject::WaitableHandle handle) override; - void UnregisterSignal(int signo); + void UnregisterSignal(int signo, void *callback_id); private: void ProcessReadObject(IOObject::WaitableHandle handle); @@ -76,14 +76,15 @@ class SignalHandle { public: - ~SignalHandle() { m_mainloop.UnregisterSignal(m_signo); } + ~SignalHandle() { m_mainloop.UnregisterSignal(m_signo, m_callback_id); } private: - SignalHandle(MainLoop &mainloop, int signo) - : m_mainloop(mainloop), m_signo(signo) {} + SignalHandle(MainLoop &mainloop, int signo, void *callback_id) + : m_mainloop(mainloop), m_signo(signo), m_callback_id(callback_id) {} MainLoop &m_mainloop; int m_signo; + void *m_callback_id; friend class MainLoop; SignalHandle(const SignalHandle &) = delete; @@ -91,7 +92,7 @@ }; struct SignalInfo { - Callback callback; + llvm::DenseMap callbacks; #if HAVE_SIGACTION struct sigaction old_action; #endif Index: lldb/source/Host/common/MainLoop.cpp =================================================================== --- lldb/source/Host/common/MainLoop.cpp +++ lldb/source/Host/common/MainLoop.cpp @@ -296,19 +296,24 @@ // We shall block the signal, then install the signal handler. The signal will // be unblocked in the Run() function to check for signal delivery. -MainLoop::SignalHandleUP -MainLoop::RegisterSignal(int signo, const Callback &callback, Status &error) { +MainLoop::SignalHandleUP MainLoop::RegisterSignal(int signo, + const Callback &callback, + Status &error, + void *callback_id) { #ifdef SIGNAL_POLLING_UNSUPPORTED error.SetErrorString("Signal polling is not supported on this platform."); return nullptr; #else - if (m_signals.find(signo) != m_signals.end()) { - error.SetErrorStringWithFormat("Signal %d already monitored.", signo); - return nullptr; + auto signal_it = m_signals.find(signo); + if (signal_it != m_signals.end()) { + assert(signal_it->second.callbacks.find(callback_id) == + signal_it->second.callbacks.end()); + signal_it->second.callbacks[callback_id] = callback; + return SignalHandleUP(new SignalHandle(*this, signo, callback_id)); } SignalInfo info; - info.callback = callback; + info.callbacks[callback_id] = callback; struct sigaction new_action; new_action.sa_sigaction = &SignalHandler; new_action.sa_flags = SA_SIGINFO; @@ -340,7 +345,7 @@ info.was_blocked = sigismember(&old_set, signo); m_signals.insert({signo, info}); - return SignalHandleUP(new SignalHandle(*this, signo)); + return SignalHandleUP(new SignalHandle(*this, signo, callback_id)); #endif } @@ -350,13 +355,21 @@ assert(erased); } -void MainLoop::UnregisterSignal(int signo) { +void MainLoop::UnregisterSignal(int signo, void *callback_id) { #if SIGNAL_POLLING_UNSUPPORTED Status("Signal polling is not supported on this platform."); #else auto it = m_signals.find(signo); assert(it != m_signals.end()); + auto cb_it = it->second.callbacks.find(callback_id); + assert(cb_it != it->second.callbacks.end()); + it->second.callbacks.erase(cb_it); + + // Do not remove the signal handler unless all callbacks have been erased. + if (!it->second.callbacks.empty()) + return; + sigaction(signo, &it->second.old_action, nullptr); sigset_t set; @@ -398,8 +411,15 @@ void MainLoop::ProcessSignal(int signo) { auto it = m_signals.find(signo); - if (it != m_signals.end()) - it->second.callback(*this); // Do the work + if (it != m_signals.end()) { + // The callback may actually register/unregister signal handlers, + // so we need to create a copy first. + llvm::SmallVector callbacks_to_run; + for (auto &x : it->second.callbacks) + callbacks_to_run.push_back(x.second); + for (auto &x : callbacks_to_run) + x(*this); // Do the work + } } void MainLoop::ProcessReadObject(IOObject::WaitableHandle handle) { Index: lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp =================================================================== --- lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -301,7 +301,7 @@ Status status; m_sigchld_handle = mainloop.RegisterSignal( - SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, status); + SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, status, this); assert(m_sigchld_handle && status.Success()); for (const auto &tid : tids) {