diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2009-07-17 15:52:27 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-07-17 15:52:27 +0200 |
| commit | 37ab187408799ba3f3f9107bdc5a72fea0b4b608 (patch) | |
| tree | b4a0a376ba97b573e8e52cdae8893a136fa8b8e2 /src/Daemon/CrashWatcher.cpp | |
| parent | 27967b17597a24e76f06871332d7a44eeb790a80 (diff) | |
| download | abrt-37ab187408799ba3f3f9107bdc5a72fea0b4b608.tar.gz abrt-37ab187408799ba3f3f9107bdc5a72fea0b4b608.tar.xz abrt-37ab187408799ba3f3f9107bdc5a72fea0b4b608.zip | |
rework unsafe handling of SIGINT/SIGTERM
Signals are asynchronous. It is unsafe to perform such complex
operations in a signal handler. I changed signal handler
to just set a flag, and added an event source which returns an event
when this variable is set. The action is to stop event loop.
Execution then falls through to program exit.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'src/Daemon/CrashWatcher.cpp')
| -rw-r--r-- | src/Daemon/CrashWatcher.cpp | 60 |
1 files changed, 58 insertions, 2 deletions
diff --git a/src/Daemon/CrashWatcher.cpp b/src/Daemon/CrashWatcher.cpp index e21d57a..73c90e0 100644 --- a/src/Daemon/CrashWatcher.cpp +++ b/src/Daemon/CrashWatcher.cpp @@ -578,12 +578,63 @@ void CCrashWatcher::StartWatch() delete[] buff; } +extern uint8_t sig_caught; +//prepare() +//If the source can determine that it is ready here (without waiting +//for the results of the poll() call) it should return TRUE. It can also +//return a timeout_ value which should be the maximum timeout (in milliseconds) +//which should be passed to the poll() call. +//check() +//Called after all the file descriptors are polled. The source should +//return TRUE if it is ready to be dispatched. +//dispatch() +//Called to dispatch the event source, after it has returned TRUE +//in either its prepare or its check function. The dispatch function +//is passed in a callback function and data. The callback function +//may be NULL if the source was never connected to a callback using +//g_source_set_callback(). The dispatch function should +//call the callback function with user_data and whatever additional +//parameters are needed for this type of event source. +typedef struct SignalSource +{ + GSource src; + CCrashWatcher* watcher; +} SignalSource; +static gboolean waitsignal_prepare(GSource *source, gint *timeout_) +{ + /* We depend on the fact that in Unix, poll() is interrupted + * by caught signals (returns EINTR). Thus we do not need to set + * a small timeout here: infinite timeout (-1) works too */ + *timeout_ = -1; + return sig_caught != 0; +} +static gboolean waitsignal_check(GSource *source) +{ + return sig_caught != 0; +} +static gboolean waitsignal_dispatch(GSource *source, GSourceFunc callback, gpointer user_data) +{ + SignalSource *ssrc = (SignalSource*) source; + ssrc->watcher->StopRun(); +} + /* daemon loop with glib */ void CCrashWatcher::GStartWatch() { - g_io_add_watch (m_pGio, G_IO_IN, handle_event_cb, this); + g_io_add_watch(m_pGio, G_IO_IN, handle_event_cb, this); + + GSourceFuncs waitsignal_funcs; + memset(&waitsignal_funcs, 0, sizeof(waitsignal_funcs)); + waitsignal_funcs.prepare = waitsignal_prepare; + waitsignal_funcs.check = waitsignal_check; + waitsignal_funcs.dispatch = waitsignal_dispatch; + //waitsignal_funcs.finalize = NULL; - already done + SignalSource *waitsignal_src = (SignalSource*) g_source_new(&waitsignal_funcs, sizeof(*waitsignal_src)); + waitsignal_src->watcher = this; + g_source_attach(&waitsignal_src->src, g_main_context_default()); + //enter the event loop - g_main_run (m_pMainloop); + g_main_run(m_pMainloop); } void CCrashWatcher::Run() @@ -594,6 +645,11 @@ void CCrashWatcher::Run() GStartWatch(); } +void CCrashWatcher::StopRun() +{ + g_main_quit(m_pMainloop); +} + vector_crash_infos_t CCrashWatcher::GetCrashInfos(const std::string &pUID) { vector_crash_infos_t retval; |
