beagle r4600 - in trunk/beagle/beagled: . IndexHelper



Author: dbera
Date: Mon Mar 10 02:52:26 2008
New Revision: 4600
URL: http://svn.gnome.org/viewvc/beagle?rev=4600&view=rev

Log:
Cleanup signal handling code. Move the common methods to Shutdown and
let classes register their specific handlers with shutdown's signal
handler thread. Remove SIGHUP hack. Remove the 5sec forceful termination
feature (if anything hangs, generally it hangs beyond the ability of the
5 sec termination).
Fix a crash in LuceneIndexingDriver.


Modified:
   trunk/beagle/beagled/BeagleDaemon.cs
   trunk/beagle/beagled/BuildIndex.cs
   trunk/beagle/beagled/IndexHelper/IndexHelper.cs
   trunk/beagle/beagled/LuceneIndexingDriver.cs
   trunk/beagle/beagled/Shutdown.cs

Modified: trunk/beagle/beagled/BeagleDaemon.cs
==============================================================================
--- trunk/beagle/beagled/BeagleDaemon.cs	(original)
+++ trunk/beagle/beagled/BeagleDaemon.cs	Mon Mar 10 02:52:26 2008
@@ -33,7 +33,6 @@
 using System.Threading;
 using Thread = System.Threading.Thread;
 using GLib;
-using Mono.Unix;
 
 using Beagle.Util;
 using Log = Beagle.Util.Log;
@@ -501,7 +500,12 @@
 			QueryDriver.Init ();
 			Server.Init ();
 
+#if MONO_1_9
+			Shutdown.SetupSignalHandlers (new Shutdown.SignalHandler (HandleSignal));
+#else
 			SetupSignalHandlers ();
+#endif
+
 			Shutdown.ShutdownEvent += OnShutdown;
 
 			main_loop = new MainLoop ();
@@ -553,108 +557,7 @@
 		}
 
 		/////////////////////////////////////////////////////////////////////////////
-#if MONO_1_9
-		private static void SetupSignalHandlers ()
-		{
-			// Force OurSignalHandler to be JITed
-			OurSignalHandler (-1);
-
-			UnixSignal[] signals = new UnixSignal [] {
-				new UnixSignal (Mono.Unix.Native.Signum.SIGINT),
-				new UnixSignal (Mono.Unix.Native.Signum.SIGTERM),
-				new UnixSignal (Mono.Unix.Native.Signum.SIGUSR1),
-				new UnixSignal (Mono.Unix.Native.Signum.SIGUSR2),
-				new UnixSignal (Mono.Unix.Native.Signum.SIGHUP) /* Use to break the signal listener itself */
-			};
-
-			// Ignore SIGPIPE
-			Mono.Unix.Native.Stdlib.SetSignalAction (Mono.Unix.Native.Signum.SIGPIPE, Mono.Unix.Native.SignalAction.Ignore);
-
-			Thread signal_thread = new Thread (delegate () {
-				Log.Debug ("Starting signal handler thread");
-				bool stop = false;
-				while (! stop) {
-					int signal = UnixSignal.WaitAny (signals, -1);
-					stop = OurSignalHandler (signal);
-				}
-				Log.Debug ("Exiting signal handler thread");
-			});
-
-			signal_thread.Start ();
-		}
-
-		// Mono signal handler allows setting of global variables;
-		// anything else e.g. function calls, even reentrant native methods are risky
-		// Returns true if the signal handler should not continue to listen to more signals
-		private static bool OurSignalHandler (int signal)
-		{
-			// This allows us to call OurSignalHandler w/o doing anything.
-			// We want to call it once to ensure that it is pre-JITed.
-			if (signal < 0 || (Mono.Unix.Native.Signum) signal == Mono.Unix.Native.Signum.SIGHUP)
-				return true;
-
-			bool ret = false;
-
-			// Set shutdown flag to true so that other threads can stop initializing
-			if ((Mono.Unix.Native.Signum) signal != Mono.Unix.Native.Signum.SIGUSR1) {
-				Shutdown.ShutdownRequested = true;
-				ret = true;
-			}
-
-			// Do all signal handling work in the main loop and not in the signal handler.
-			GLib.Idle.Add (new GLib.IdleHandler (delegate () { HandleSignal (signal); return false; }));
-
-			return ret;
-		}
-
-		private static void HandleSignal (int signal)
-		{
-			Logger.Log.Debug ("Handling signal {0} ({1})", signal, (Mono.Unix.Native.Signum) signal);
-
-			// If we get SIGUSR1, turn the debugging level up.
-			if ((Mono.Unix.Native.Signum) signal == Mono.Unix.Native.Signum.SIGUSR1) {
-				LogLevel old_level = Log.Level;
-				Log.Level = LogLevel.Debug;
-				Log.Debug ("Moving from log level {0} to Debug", old_level);
-			}
-
-			// Send informational signals to the helper too.
-			if ((Mono.Unix.Native.Signum) signal == Mono.Unix.Native.Signum.SIGUSR1 ||
-			    (Mono.Unix.Native.Signum) signal == Mono.Unix.Native.Signum.SIGUSR2) {
-				GLib.Idle.Add (new GLib.IdleHandler (delegate () { RemoteIndexer.SignalRemoteIndexer ((Mono.Unix.Native.Signum) signal); return false; }));
-				return;
-			}
-
-			Logger.Log.Debug ("Initiating shutdown in response to signal.");
-			Shutdown.BeginShutdown ();
-		}
-
-		/////////////////////////////////////////////////////////////////////////////
-
-		private static void OnShutdown ()
-		{
-#if ENABLE_AVAHI
-			zeroconf.Dispose ();
-#endif			
-			// Send a signal to index-helper (if we miss this, even then index-helper will see the daemon going away and kill itself)
-			RemoteIndexer.SignalRemoteIndexer (Mono.Unix.Native.Signum.SIGINT);
-
-			// Stop our Inotify threads
-			Inotify.Stop ();
 
-			// Stop the global scheduler and ask it to shutdown
-			Scheduler.Global.Stop (true);
-
-			// Stop the messaging server
-			if (server != null)
-				server.Stop ();
-
-			// Stop the signal handler thread by sending a fake SIGHUP signal
-			Mono.Unix.Native.Syscall.kill (Process.GetCurrentProcess ().Id, Mono.Unix.Native.Signum.SIGHUP);
-		}
-
-		/////////////////////////////////////////////////////////////////////////////
-#else
 		private static void SetupSignalHandlers ()
 		{
 			// Force OurSignalHandler to be JITed
@@ -698,10 +601,15 @@
 				Log.Debug ("Moving from log level {0} to Debug", old_level);
 			}
 
-			// Send informational signals to the helper too.
+			// Pass the signals to the helper too.
+			GLib.Idle.Add (new GLib.IdleHandler (delegate ()
+							    {
+								    RemoteIndexer.SignalRemoteIndexer ((Mono.Unix.Native.Signum) signal);
+								    return false; 
+							    }));
+
 			if ((Mono.Unix.Native.Signum) signal == Mono.Unix.Native.Signum.SIGUSR1 ||
 			    (Mono.Unix.Native.Signum) signal == Mono.Unix.Native.Signum.SIGUSR2) {
-				GLib.Idle.Add (new GLib.IdleHandler (delegate () { RemoteIndexer.SignalRemoteIndexer ((Mono.Unix.Native.Signum) signal); return false; }));
 				return;
 			}
 
@@ -726,7 +634,6 @@
 			if (server != null)
 				server.Stop ();
 		}
-#endif
 
 		/////////////////////////////////////////////////////////////////////////////
 

Modified: trunk/beagle/beagled/BuildIndex.cs
==============================================================================
--- trunk/beagle/beagled/BuildIndex.cs	(original)
+++ trunk/beagle/beagled/BuildIndex.cs	Mon Mar 10 02:52:26 2008
@@ -354,7 +354,16 @@
 			fa_store = new FileAttributesStore (backing_fa_store);
 			
 			// Set up signal handlers
+#if MONO_1_9
+			Shutdown.SetupSignalHandlers (delegate (int signal)
+							{
+								if (signal == (int) Mono.Unix.Native.Signum.SIGINT ||
+								    signal == (int) Mono.Unix.Native.Signum.SIGTERM)
+									Shutdown.BeginShutdown ();
+							});
+#else
 			SetupSignalHandlers ();
+#endif
 
 			Thread monitor_thread = null;
 

Modified: trunk/beagle/beagled/IndexHelper/IndexHelper.cs
==============================================================================
--- trunk/beagle/beagled/IndexHelper/IndexHelper.cs	(original)
+++ trunk/beagle/beagled/IndexHelper/IndexHelper.cs	Mon Mar 10 02:52:26 2008
@@ -34,7 +34,6 @@
 using System.Threading;
 
 using GLib;
-using Mono.Unix;
 
 using Beagle.Daemon;
 using Beagle.Util;
@@ -138,7 +137,11 @@
 
 			Server.Init ();
 
+#if MONO_1_9
+			Shutdown.SetupSignalHandlers (new Shutdown.SignalHandler (HandleSignal));
+#else
 			SetupSignalHandlers ();
+#endif
 
 			Shutdown.ShutdownEvent += OnShutdown;
 
@@ -281,100 +284,6 @@
 		}
 
 		/////////////////////////////////////////////////////////////////////////////
-#if MONO_1_9
-		private static void SetupSignalHandlers ()
-		{
-			// Force OurSignalHandler to be JITed
-			OurSignalHandler (-1);
-
-			UnixSignal[] signals = new UnixSignal [] {
-				new UnixSignal (Mono.Unix.Native.Signum.SIGINT),
-				new UnixSignal (Mono.Unix.Native.Signum.SIGTERM),
-				new UnixSignal (Mono.Unix.Native.Signum.SIGUSR1),
-				new UnixSignal (Mono.Unix.Native.Signum.SIGUSR2),
-				new UnixSignal (Mono.Unix.Native.Signum.SIGHUP) /* Use to break the signal listener itself */
-			};
-
-			// Ignore SIGPIPE
-			Mono.Unix.Native.Stdlib.SetSignalAction (Mono.Unix.Native.Signum.SIGPIPE, Mono.Unix.Native.SignalAction.Ignore);
-
-			Thread signal_thread = new Thread (delegate () {
-				Log.Debug ("Starting signal handler thread");
-				bool shutdown = false;
-				while (! shutdown) {
-					int signal = UnixSignal.WaitAny (signals, -1);
-					shutdown = OurSignalHandler (signal);
-				}
-				Log.Debug ("Exiting signal handler thread");
-			});
-
-			signal_thread.Start ();
-		}
-
-		// Returns true if the signal handler should not continue to listen to more signals
-		private static bool OurSignalHandler (int signal)
-		{
-			// This allows us to call OurSignalHandler w/o doing anything.
-			// We want to call it once to ensure that it is pre-JITed.
-			if (signal < 0 || (Mono.Unix.Native.Signum) signal == Mono.Unix.Native.Signum.SIGHUP)
-				return true;
-
-			bool ret = false;
-
-			// SIGUSR1 and SIGUSR2 are informational signals.  For other
-			// signals that we handle, set the shutdown flag to true so
-			// that other threads can stop initializing
-			if ((Mono.Unix.Native.Signum) signal != Mono.Unix.Native.Signum.SIGUSR1 &&
-			    (Mono.Unix.Native.Signum) signal != Mono.Unix.Native.Signum.SIGUSR2) {
-				Shutdown.ShutdownRequested = true;
-				ret = true;
-			}
-
-			// Do all signal handling work in the main loop and not in the signal handler.
-			GLib.Idle.Add (new GLib.IdleHandler (delegate () { HandleSignal (signal); return false; }));
-
-			return ret;
-		}
-
-		private static void HandleSignal (int signal)
-		{
-			Log.Warn ("Handling signal {0} ({1})", signal, (Mono.Unix.Native.Signum) signal);
-
-			// If we get SIGUSR1, turn the debugging level up.
-			if ((Mono.Unix.Native.Signum) signal == Mono.Unix.Native.Signum.SIGUSR1) {
-				LogLevel old_level = Log.Level;
-				Log.Level = LogLevel.Debug;
-				Log.Debug ("Moving from log level {0} to Debug", old_level);
-			}
-
-			string span = StringFu.TimeSpanToString (DateTime.Now - last_activity);
-
-			if (CurrentDisplayUri == null)
-				Log.Warn ("Filtering status ({0} ago): no document is currently being filtered.", span);
-			else if (CurrentFilter == null)
-				Log.Warn ("Filtering status ({0} ago): determining filter and extracting properties for {1} ({2})", span, CurrentDisplayUri, CurrentContentUri);
-			else
-				Log.Warn ("Filtering status ({0} ago): extracting text from {1} ({2}) with {3}", span, CurrentDisplayUri, CurrentContentUri, CurrentFilter);
-
-			// Don't shut down on information signals (SIGUSR1 and SIGUSR2)
-			if ((Mono.Unix.Native.Signum) signal == Mono.Unix.Native.Signum.SIGUSR1 ||
-			    (Mono.Unix.Native.Signum) signal == Mono.Unix.Native.Signum.SIGUSR2)
-				return;
-
-			Logger.Log.Debug ("Initiating shutdown in response to signal.");
-			Shutdown.BeginShutdown ();
-		}
-
-		private static void OnShutdown ()
-		{
-			if (server != null)
-				server.Stop ();
-
-			// Stop the signal handler thread by sending a fake SIGHUP signal
-			Mono.Unix.Native.Syscall.kill (Process.GetCurrentProcess ().Id, Mono.Unix.Native.Signum.SIGHUP);
-		}
-
-#else
 
 		private static void SetupSignalHandlers ()
 		{
@@ -443,7 +352,6 @@
 			if (server != null)
 				server.Stop ();
 		}
-#endif
 	}
 
 }

Modified: trunk/beagle/beagled/LuceneIndexingDriver.cs
==============================================================================
--- trunk/beagle/beagled/LuceneIndexingDriver.cs	(original)
+++ trunk/beagle/beagled/LuceneIndexingDriver.cs	Mon Mar 10 02:52:26 2008
@@ -357,6 +357,7 @@
 			if (Shutdown.ShutdownRequested) {
 				foreach (DeferredInfo di in deferred_indexables)
 					di.Cleanup ();
+				deferred_indexables.Clear ();
 
 				foreach (Indexable indexable in request_indexables)
 					indexable.Cleanup ();
@@ -503,6 +504,7 @@
 			if (Shutdown.ShutdownRequested) {
 				foreach (DeferredInfo di in deferred_indexables)
 					di.Cleanup ();
+				deferred_indexables.Clear ();
 
 				primary_writer.Close ();
 				if (secondary_writer != null)
@@ -725,6 +727,7 @@
 			lock (flush_lock) {
 				foreach (DeferredInfo di in deferred_indexables)
 					di.Cleanup ();
+				deferred_indexables.Clear ();
 			}
 		}
 	}

Modified: trunk/beagle/beagled/Shutdown.cs
==============================================================================
--- trunk/beagle/beagled/Shutdown.cs	(original)
+++ trunk/beagle/beagled/Shutdown.cs	Mon Mar 10 02:52:26 2008
@@ -27,7 +27,9 @@
 using System;
 using System.Threading;
 using System.Collections;
+using System.Diagnostics;
 using Beagle.Util;
+using Mono.Unix;
 
 namespace Beagle.Daemon {
 
@@ -40,6 +42,7 @@
 		static Hashtable workers_names = new Hashtable ();
 		static bool shutdownRequested = false;
 		static bool shutdownStarted = false;
+		static bool mainloop_finished = false;
 
 		public delegate void ShutdownHandler ();
 		public static event ShutdownHandler ShutdownEvent;
@@ -108,14 +111,6 @@
 			main_loop = loop;
 		}
 
-		// Our handler triggers an orderly shutdown when it receives a signal.
-		// However, this can be annoying if the process gets wedged during
-		// shutdown.  To deal with that case, we make a note of the time when
-		// the first signal comes in, and we allow signals to unconditionally
-		// kill the process after 5 seconds have passed.
-
-		static DateTime signal_time = DateTime.MinValue;
-
 		public static void BeginShutdown ()
 		{
 			lock (shutdownLock) {
@@ -129,31 +124,7 @@
 				shutdownStarted = true;
 			}
 
-			// FIXME: This whole "unconditional killing after 5 seconds because
-			// beagled can hang while shutting down" thing should not occur. Any such
-			// incident should be immediately investigated and fixed. Hint: Sending
-			// kill -quit `pidof beagled` will probably reveal that beagled got locked
-			// when signal handler was called and some thread was executing some native
-			// method.
-			bool first_signal = false;
-			if (signal_time == DateTime.MinValue) {
-				Log.Always ("Shutdown requested");
-				signal_time = DateTime.Now;
-				first_signal = true;
-			}
-
-			if (! first_signal) {
-				double t = (DateTime.Now - signal_time).TotalSeconds;
-				const double min_t = 5;
-
-				if (t < min_t) {
-					Logger.Log.Debug ("Signals can force an immediate shutdown in {0:0.00}s", min_t-t);
-					return;
-				} else {
-					Logger.Log.Debug ("Forcing immediate shutdown.");
-					Environment.Exit (0);
-				}
-			}
+			Log.Always ("Shutdown requested");
 
 			if (ShutdownEvent != null) {
 				try {
@@ -180,6 +151,70 @@
 
 			Logger.Log.Info ("All workers have finished.  Exiting main loop.");
 			main_loop.Quit ();
+
+#if MONO_1_9
+			// So (re)sending a SIGTERM or SIGINT after mainloop is over will kill the process.
+			// Is it good or bad ? (some of the exception handling thread might still be running)
+			// I think its good; it sort of emulates the 5sec forceful killing feature of < 0.3.4 
+			lock (shutdownLock)
+				mainloop_finished = true;
+
+			// Stop the signal handler thread by sending a signal
+			Mono.Unix.Native.Syscall.kill (Process.GetCurrentProcess ().Id, Mono.Unix.Native.Signum.SIGINT);
+#endif
+		}
+
+#if MONO_1_9
+		static bool MainloopFinished {
+			get {
+				lock (shutdownLock)
+					return mainloop_finished;
+			}
+		}
+
+		public delegate void SignalHandler (int signal);
+
+		public static void SetupSignalHandlers (SignalHandler signal_handler)
+		{
+			UnixSignal[] signals = new UnixSignal [] {
+				new UnixSignal (Mono.Unix.Native.Signum.SIGINT),
+				new UnixSignal (Mono.Unix.Native.Signum.SIGTERM),
+				new UnixSignal (Mono.Unix.Native.Signum.SIGUSR1),
+				new UnixSignal (Mono.Unix.Native.Signum.SIGUSR2)
+			};
+
+			// Ignore SIGPIPE
+			// FIXME: Shouldn't this be done in every thread ?
+			Mono.Unix.Native.Stdlib.SetSignalAction (Mono.Unix.Native.Signum.SIGPIPE, Mono.Unix.Native.SignalAction.Ignore);
+
+			Thread signal_thread = new Thread (delegate () {
+				Log.Debug ("Starting signal handler thread");
+				int signal_handler_timeout = -1;
+				while (! MainloopFinished) {
+					int index = UnixSignal.WaitAny (signals, signal_handler_timeout);
+
+					if (index > 3)
+						continue;
+					Mono.Unix.Native.Signum signal = signals [index].Signum;
+
+					// Set shutdown flag to true so that other threads can stop initializing
+					if (signal == Mono.Unix.Native.Signum.SIGINT ||
+					    signal == Mono.Unix.Native.Signum.SIGTERM) {
+						ShutdownRequested = true;
+						signal_handler_timeout = 200; // 200 ms
+					}
+
+					if (signal_handler == null)
+						continue;
+
+					// Do all signal handling work in the main loop and not in the signal handler.
+					GLib.Idle.Add (new GLib.IdleHandler (delegate () { signal_handler ((int) signal); return false; }));
+				}
+				Log.Debug ("Exiting signal handler thread");
+			});
+
+			signal_thread.Start ();
 		}
+#endif
 	}
 }



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