mgorny updated this revision to Diff 337539.
mgorny edited the summary of this revision.
mgorny added a comment.
Store callbacks in `std::list`, and use the list iterator to identify the
callback to remove.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D100418/new/
https://reviews.llvm.org/D100418
Files:
lldb/include/lldb/Host/MainLoop.h
lldb/source/Host/common/MainLoop.cpp
Index: lldb/source/Host/common/MainLoop.cpp
===================================================================
--- lldb/source/Host/common/MainLoop.cpp
+++ lldb/source/Host/common/MainLoop.cpp
@@ -302,13 +302,15 @@
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()) {
+ auto callback_it = signal_it->second.callbacks.insert(
+ signal_it->second.callbacks.end(), callback);
+ return SignalHandleUP(new SignalHandle(*this, signo, callback_it));
}
SignalInfo info;
- info.callback = callback;
+ auto callback_it = info.callbacks.insert(info.callbacks.end(), callback);
struct sigaction new_action;
new_action.sa_sigaction = &SignalHandler;
new_action.sa_flags = SA_SIGINFO;
@@ -340,7 +342,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_it));
#endif
}
@@ -350,13 +352,19 @@
assert(erased);
}
-void MainLoop::UnregisterSignal(int signo) {
+void MainLoop::UnregisterSignal(int signo,
+ std::list<Callback>::iterator callback_it) {
#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());
+ it->second.callbacks.erase(callback_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 +406,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<Callback, 4> callbacks_to_run;
+ for (auto &x : it->second.callbacks)
+ callbacks_to_run.push_back(x);
+ for (auto &x : callbacks_to_run)
+ x(*this); // Do the work
+ }
}
void MainLoop::ProcessReadObject(IOObject::WaitableHandle handle) {
Index: lldb/include/lldb/Host/MainLoop.h
===================================================================
--- lldb/include/lldb/Host/MainLoop.h
+++ lldb/include/lldb/Host/MainLoop.h
@@ -13,6 +13,7 @@
#include "lldb/Host/MainLoopBase.h"
#include "llvm/ADT/DenseMap.h"
#include <csignal>
+#include <list>
#if !HAVE_PPOLL && !HAVE_SYS_EVENT_H && !defined(__ANDROID__)
#define SIGNAL_POLLING_UNSUPPORTED 1
@@ -68,7 +69,7 @@
protected:
void UnregisterReadObject(IOObject::WaitableHandle handle) override;
- void UnregisterSignal(int signo);
+ void UnregisterSignal(int signo, std::list<Callback>::iterator callback_it);
private:
void ProcessReadObject(IOObject::WaitableHandle handle);
@@ -76,14 +77,16 @@
class SignalHandle {
public:
- ~SignalHandle() { m_mainloop.UnregisterSignal(m_signo); }
+ ~SignalHandle() { m_mainloop.UnregisterSignal(m_signo, m_callback_it); }
private:
- SignalHandle(MainLoop &mainloop, int signo)
- : m_mainloop(mainloop), m_signo(signo) {}
+ SignalHandle(MainLoop &mainloop, int signo,
+ std::list<Callback>::iterator callback_it)
+ : m_mainloop(mainloop), m_signo(signo), m_callback_it(callback_it) {}
MainLoop &m_mainloop;
int m_signo;
+ std::list<Callback>::iterator m_callback_it;
friend class MainLoop;
SignalHandle(const SignalHandle &) = delete;
@@ -91,7 +94,7 @@
};
struct SignalInfo {
- Callback callback;
+ std::list<Callback> callbacks;
#if HAVE_SIGACTION
struct sigaction old_action;
#endif
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits