[evolution-activesync/for-master/pohly: 1/3] activesyncd: fix signal handler



commit d1a0d0c8b12b06ba433e65e18b3dad9baec746f5
Author: Patrick Ohly <patrick ohly intel com>
Date:   Wed Sep 5 12:10:17 2012 +0000

    activesyncd: fix signal handler
    
    Sometimes in SyncEvolution's nightly testing the activesyncd dies
    with a crash after being sent a SIGTERM and a SIGINT (both are
    sent because the sending script is used for more than activesyncd
    and doesn't know which one will work).
    
    The debug output in that case shows:
    
    (process:20189): activesyncd-DEBUG (recursed): signalHandler++
    
    (process:20189): activesyncd-DEBUG (recursed): signalHandler++
    
    ...
    
    Apparently at some point the process runs out of memory, or gets
    killed with SIGKILL after not shutting down in a timely manner (don't
    remember).
    
    This patch solves several issues with signal handler and seems to help:
    - Don't produce IO in the signal because it is uncertain
      whether that is allowed.
    - Don't leave a dangling GMainLoop pointer in g_mainloop after
      freeing it (probably the reason for the crash).
    - Avoid a race condition by clearing g_mainloop before freeing it.
    
    I also think catching SIGABRT is a bad idea because if something
    catastrophic happens and raises that signal, the process should
    shut down abnormally. I left it in place for now.

 eas-daemon/src/activesyncd-server.c |   39 ++++++++++++++++++++--------------
 1 files changed, 23 insertions(+), 16 deletions(-)
---
diff --git a/eas-daemon/src/activesyncd-server.c b/eas-daemon/src/activesyncd-server.c
index 6271cce..f58808b 100644
--- a/eas-daemon/src/activesyncd-server.c
+++ b/eas-daemon/src/activesyncd-server.c
@@ -145,11 +145,13 @@ void eas_logger (const gchar *log_domain,
 
 void signalHandler (int sig)
 {
-	g_debug ("signalHandler++\n");
-
-	g_main_loop_quit (g_mainloop);
-
-	g_debug ("signalHandler--\n");
+	if (g_mainloop) {
+		// Only quit the loop once. Doing it again
+		// leads to a race condition (main() unrefs
+		// loop, we use it again here).
+		g_main_loop_quit (g_mainloop);
+		g_mainloop = NULL;
+	}
 }
 
 /*
@@ -163,6 +165,7 @@ int main (int argc, char** argv)
 	EasCommon* EasCommonObj = NULL;
 	EasMail*EasMailObj = NULL;
 	EasTest* EasTestObj = NULL;
+	GMainLoop* loop = NULL;
 
 	guint result;
 	GError* error = NULL;
@@ -181,12 +184,15 @@ int main (int argc, char** argv)
 	signal (SIGTERM, &signalHandler);
 	signal (SIGINT, &signalHandler);
 
-	g_mainloop = g_main_loop_new (NULL, FALSE);
-	if (g_mainloop == NULL) {
+	loop = g_main_loop_new (NULL, FALSE);
+	if (loop == NULL) {
 		g_debug ("Error: Couldn't create GMainLoop");
 		exit (EXIT_FAILURE);
 	}
 
+	// Give signalHandler() access to the main loop.
+	g_mainloop = loop;
+
 	//Creating all the GObjects
 	g_debug ("activesyncd Daemon Started");
 
@@ -194,7 +200,7 @@ int main (int argc, char** argv)
 	EasSyncObj = eas_sync_new();
 	if (EasSyncObj == NULL) {
 		g_debug ("Error: Failed to create calendar  instance");
-		g_main_loop_quit (g_mainloop);
+		g_main_loop_quit (loop);
 		exit (EXIT_FAILURE);
 	}
 
@@ -202,7 +208,7 @@ int main (int argc, char** argv)
 	EasCommonObj = g_object_new (EAS_TYPE_COMMON , NULL);
 	if (EasCommonObj == NULL) {
 		g_debug ("Error: Failed to create common  instance");
-		g_main_loop_quit (g_mainloop);
+		g_main_loop_quit (loop);
 		exit (EXIT_FAILURE);
 	}
 
@@ -210,14 +216,14 @@ int main (int argc, char** argv)
 	EasMailObj = eas_mail_new ();
 	if (EasMailObj == NULL) {
 		g_debug ("Error: Failed to create common  instance");
-		g_main_loop_quit (g_mainloop);
+		g_main_loop_quit (loop);
 		exit (EXIT_FAILURE);
 	}
 
 	EasTestObj = eas_test_new ();
 	if (NULL == EasTestObj) {
 		g_debug ("Failed to make EasTest instance");
-		g_main_loop_quit (g_mainloop);
+		g_main_loop_quit (loop);
 		exit (EXIT_FAILURE);
 	}
 
@@ -226,7 +232,7 @@ int main (int argc, char** argv)
 	if (error != NULL) {
 		g_debug ("Error: Connecting to the session DBus (%s)", error->message);
 		g_clear_error (&error);
-		g_main_loop_quit (g_mainloop);
+		g_main_loop_quit (loop);
 		exit (EXIT_FAILURE);
 	}
 
@@ -237,7 +243,7 @@ int main (int argc, char** argv)
 					      DBUS_INTERFACE_DBUS);
 	if (busProxy == NULL) {
 		g_debug ("Error: Failed to get a proxy for D-Bus");
-		g_main_loop_quit (g_mainloop);
+		g_main_loop_quit (loop);
 		exit (EXIT_FAILURE);
 	}
 
@@ -258,7 +264,7 @@ int main (int argc, char** argv)
 				G_TYPE_INVALID)) {
 		g_debug ("Error: D-Bus RequestName RPC failed (%s)", error->message);
 		g_clear_error (&error);
-		g_main_loop_quit (g_mainloop);
+		g_main_loop_quit (loop);
 		exit (EXIT_FAILURE);
 	}
 
@@ -297,11 +303,12 @@ int main (int argc, char** argv)
 	g_debug ("Not daemonizing (built with DISABLE_EAS_DAEMON)");
 #endif
 
-	g_main_loop_run (g_mainloop);
+	g_main_loop_run (loop);
 
 	// Clean up
 	g_debug ("Main Cleanup");
-	g_main_loop_unref (g_mainloop);
+	g_mainloop = NULL;
+	g_main_loop_unref (loop);
 
 	// clean up dbus and all its objects
 	if (EasSyncObj) {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]