summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-07-17 15:52:27 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2009-07-17 15:52:27 +0200
commit37ab187408799ba3f3f9107bdc5a72fea0b4b608 (patch)
treeb4a0a376ba97b573e8e52cdae8893a136fa8b8e2 /src
parent27967b17597a24e76f06871332d7a44eeb790a80 (diff)
downloadabrt-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.cpp60
-rw-r--r--src/Daemon/CrashWatcher.h5
-rw-r--r--src/Daemon/Daemon.cpp16
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 */
}