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 | |
| 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')
| -rw-r--r-- | src/Daemon/CrashWatcher.cpp | 60 | ||||
| -rw-r--r-- | src/Daemon/CrashWatcher.h | 5 | ||||
| -rw-r--r-- | src/Daemon/Daemon.cpp | 16 |
3 files changed, 69 insertions, 12 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; diff --git a/src/Daemon/CrashWatcher.h b/src/Daemon/CrashWatcher.h index e512478..d19da17 100644 --- a/src/Daemon/CrashWatcher.h +++ b/src/Daemon/CrashWatcher.h @@ -96,11 +96,12 @@ class CCrashWatcher /*FIXME not needed */ //DBus::Connection *m_pConn; CSettings *m_pSettings; - public: + public: //CCrashWatcher(const std::string& pPath,DBus::Connection &connection); CCrashWatcher(const std::string& pPath); - virtual ~CCrashWatcher(); + virtual ~CCrashWatcher(); void Run(); + void StopRun(); /* methods exported on dbus */ public: diff --git a/src/Daemon/Daemon.cpp b/src/Daemon/Daemon.cpp index ea769c5..c28331f 100644 --- a/src/Daemon/Daemon.cpp +++ b/src/Daemon/Daemon.cpp @@ -25,15 +25,15 @@ #include <sys/stat.h> #include <fcntl.h> -CCrashWatcher *g_pCrashWatcher = NULL; +uint8_t sig_caught; -void terminate(int signal) +static void handle_fatal_signal(int signal) { - fprintf(stderr, "Got SIGINT/SIGTERM, cleaning up..\n"); - delete g_pCrashWatcher; - exit(0); + sig_caught = signal; } +CCrashWatcher *g_pCrashWatcher = NULL; + void print_help() { @@ -43,8 +43,8 @@ int main(int argc, char** argv) { int daemonize = 1; /*signal handlers */ - signal(SIGTERM, terminate); - signal(SIGINT, terminate); + signal(SIGTERM, handle_fatal_signal); + signal(SIGINT, handle_fatal_signal); try { @@ -97,7 +97,7 @@ int main(int argc, char** argv) { std::cerr << "Cannot create daemon: " << e.what() << std::endl; } - //do we need this? delete g_pCrashWatcher; + delete g_pCrashWatcher; return 1; /* Any exit is a failure. Normally we don't exit at all */ } |
