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

[vidalia-svn] r3787: Add a signal handler that allows Vidalia to clean up and exi (in vidalia/trunk: . src/vidalia)



Author: edmanm
Date: 2009-05-21 01:27:21 -0400 (Thu, 21 May 2009)
New Revision: 3787

Modified:
   vidalia/trunk/CHANGELOG
   vidalia/trunk/CMakeLists.txt
   vidalia/trunk/config.h.in
   vidalia/trunk/src/vidalia/MainWindow.cpp
   vidalia/trunk/src/vidalia/MainWindow.h
   vidalia/trunk/src/vidalia/Vidalia.cpp
   vidalia/trunk/src/vidalia/Vidalia.h
   vidalia/trunk/src/vidalia/main.cpp
Log:

Add a signal handler that allows Vidalia to clean up and exit normally
when it catches a SIGINT or SIGTERM signal. (Ticket #481)


Modified: vidalia/trunk/CHANGELOG
===================================================================
--- vidalia/trunk/CHANGELOG	2009-05-21 01:49:36 UTC (rev 3786)
+++ vidalia/trunk/CHANGELOG	2009-05-21 05:27:21 UTC (rev 3787)
@@ -9,6 +9,8 @@
     now defaults to using port 443 in such cases.
   o Add support for viewing the map as a full screen widget when built
     with KDE Marble support.
+  o Add a signal handler that allows Vidalia to clean up and exit normally
+    when it catches a SIGINT or SIGTERM signal. (Ticket #481)
   o Renamed the 'make win32-installer' CMake target to 'make dist-win32'
     for consistency with our 'make dist-osx' target.
   o Fix a couple bugs in the WiX-based Windows installer related to building

Modified: vidalia/trunk/CMakeLists.txt
===================================================================
--- vidalia/trunk/CMakeLists.txt	2009-05-21 01:49:36 UTC (rev 3786)
+++ vidalia/trunk/CMakeLists.txt	2009-05-21 05:27:21 UTC (rev 3787)
@@ -48,6 +48,7 @@
 include(CheckIncludeFile)
 include(CheckIncludeFileCXX)
 include(CheckTypeSize)
+include(CheckFunctionExists)
 if (WIN32)
   include(${CMAKE_SOURCE_DIR}/cmake/FindWiX.cmake)
 endif(WIN32)
@@ -88,10 +89,18 @@
 ## Check for system header files
 check_include_file("limits.h" HAVE_LIMITS_H)
 check_include_file("sys/limits.h" HAVE_SYS_LIMITS_H)
+check_include_file("signal.h" HAVE_SIGNAL_H)
 
 ## Check for the sizes of various data types
 check_type_size(int SIZEOF_INT)
 
+## Check for the existence of some platform-specific functions
+if (HAVE_SIGNAL_H)
+  set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} "signal.h")
+  check_function_exists(sigaction HAVE_SIGACTION)
+  check_function_exists(signal HAVE_SIGNAL)
+endif(HAVE_SIGNAL_H)
+
 ## Write out a configuration file
 configure_file(
   ${CMAKE_CURRENT_SOURCE_DIR}/config.h.in

Modified: vidalia/trunk/config.h.in
===================================================================
--- vidalia/trunk/config.h.in	2009-05-21 01:49:36 UTC (rev 3786)
+++ vidalia/trunk/config.h.in	2009-05-21 05:27:21 UTC (rev 3787)
@@ -20,6 +20,12 @@
 
 #cmakedefine HAVE_SYS_LIMITS_H
 
+#cmakedefine HAVE_SIGNAL_H
+
+#cmakedefine HAVE_SIGACTION
+
+#cmakedefine HAVE_SIGNAL
+
 #cmakedefine SIZEOF_INT @SIZEOF_INT@
 
 #cmakedefine USE_MINIUPNPC

Modified: vidalia/trunk/src/vidalia/MainWindow.cpp
===================================================================
--- vidalia/trunk/src/vidalia/MainWindow.cpp	2009-05-21 01:49:36 UTC (rev 3786)
+++ vidalia/trunk/src/vidalia/MainWindow.cpp	2009-05-21 05:27:21 UTC (rev 3787)
@@ -169,7 +169,7 @@
 
   /* Catch signals when the application is running or shutting down */
   connect(vApp, SIGNAL(running()), this, SLOT(running()));
-  connect(vApp, SIGNAL(shutdown()), this, SLOT(shutdown()));
+  connect(vApp, SIGNAL(aboutToQuit()), this, SLOT(aboutToQuit()));
 
 #if defined(USE_AUTOUPDATE)
   /* Create a timer used to remind us to check for software updates */
@@ -368,8 +368,10 @@
 /** Terminate the Tor process if it is being run under Vidalia, disconnect all
  * TorControl signals, and exit Vidalia. */
 void
-MainWindow::shutdown()
+MainWindow::aboutToQuit()
 {
+  vNotice("Cleaning up before exiting.");
+
   if (_torControl->isVidaliaRunningTor()) {
     /* Kill our Tor process now */ 
     _torControl->stop();
@@ -408,9 +410,6 @@
 
   /* Disconnect all of the TorControl object's signals */
   QObject::disconnect(_torControl, 0, 0, 0);
-
-  /* And then quit for real */
-  QCoreApplication::quit();
 }
 
 /** Called when the application is closing, by selecting "Exit" from the tray
@@ -425,14 +424,13 @@
      * kill Tor and bail now. */
     ServerSettings settings(_torControl);
     if (_torControl->isConnected() && settings.isServerEnabled()) {
-      connect(_torControl, SIGNAL(stopped()), this, SLOT(shutdown()));
+      connect(_torControl, SIGNAL(stopped()), vApp, SLOT(quit()));
       if (!stop())
-        QObject::disconnect(_torControl, SIGNAL(stopped()), this, SLOT(shutdown()));
+        QObject::disconnect(_torControl, SIGNAL(stopped()), vApp, SLOT(quit()));
       return;
     }
   }
-  /* Shut down Tor (if necessary) and exit Vidalia */
-  shutdown();
+  vApp->quit();
 }
 
 /** Create and bind actions to events. Setup for initial
@@ -688,7 +686,7 @@
   if (browserDone && imDone) {
     if (browserDirectory.isEmpty()) {
       /* We are using the standard launcher, exit immediately */
-      shutdown();
+      vApp->quit();
     } else {
       /* We are using the alternate launcher, wait until the browser has really died */
       QTimer *browserWatcher = new QTimer(this);

Modified: vidalia/trunk/src/vidalia/MainWindow.h
===================================================================
--- vidalia/trunk/src/vidalia/MainWindow.h	2009-05-21 01:49:36 UTC (rev 3786)
+++ vidalia/trunk/src/vidalia/MainWindow.h	2009-05-21 05:27:21 UTC (rev 3787)
@@ -106,7 +106,7 @@
   void running();
   /** Terminate the Tor process if it is being run under Vidalia, disconnect
    * all TorControl signals, and exit Vidalia. */
-  void shutdown();
+  void aboutToQuit();
   /** Creates and displays Vidalia's About dialog. */
   void showAboutDialog();
   /** Creates and displays the Configuration dialog with the current page set

Modified: vidalia/trunk/src/vidalia/Vidalia.cpp
===================================================================
--- vidalia/trunk/src/vidalia/Vidalia.cpp	2009-05-21 01:49:36 UTC (rev 3786)
+++ vidalia/trunk/src/vidalia/Vidalia.cpp	2009-05-21 05:27:21 UTC (rev 3787)
@@ -174,7 +174,7 @@
 Vidalia::winEventFilter(MSG *msg, long *result)
 {
   if (msg->message == WM_QUERYENDSESSION) {
-    emit shutdown();
+    quit();
   }
   return QApplication::winEventFilter(msg, result);
 }

Modified: vidalia/trunk/src/vidalia/Vidalia.h
===================================================================
--- vidalia/trunk/src/vidalia/Vidalia.h	2009-05-21 01:49:36 UTC (rev 3786)
+++ vidalia/trunk/src/vidalia/Vidalia.h	2009-05-21 05:27:21 UTC (rev 3787)
@@ -118,8 +118,6 @@
   /** Emitted when the application is running and the main event loop has
    * started. */ 
   void running();
-  /** Signals that the application needs to shutdown now. */
-  void shutdown();
 
 protected:
 #if defined(Q_OS_WIN)
@@ -135,7 +133,7 @@
    * will emit the running() signal to indicate that the application's event
    * loop is running. */
   void onEventLoopStarted();
-  
+ 
 private:
   /** Catches debugging messages from Qt and sends them to 
    * Vidalia's logs. */

Modified: vidalia/trunk/src/vidalia/main.cpp
===================================================================
--- vidalia/trunk/src/vidalia/main.cpp	2009-05-21 01:49:36 UTC (rev 3786)
+++ vidalia/trunk/src/vidalia/main.cpp	2009-05-21 05:27:21 UTC (rev 3787)
@@ -27,8 +27,43 @@
 #if defined(Q_OS_WIN32)
 #include <QSysInfo>
 #endif
+#if defined(HAVE_SIGNAL_H)
+#include <signal.h>
+#endif
 
 
+extern "C" void
+signal_handler(int signal)
+{
+#ifdef HAVE_SIGNAL_H
+  if (signal == SIGINT || signal == SIGTERM)
+    vApp->quit();
+#endif
+}
+
+void
+install_signal_handler()
+{
+#ifdef HAVE_SIGACTION
+  struct sigaction action;
+  
+  sigemptyset(&action.sa_mask);
+  action.sa_handler = signal_handler;
+  action.sa_flags   = 0;
+
+  if (sigaction(SIGINT,  &action, NULL) < 0)
+    vWarn("Failed to install SIGINT handler.");
+  if (sigaction(SIGTERM, &action, NULL) < 0)
+    vWarn("Failed to install SIGTERM handler.");
+#elif HAVE_SIGNAL
+  if (signal(SIGINT, signal_handler) == SIG_ERR)
+    vWarn("Failed to install SIGINT handler.");
+  if (signal(SIGTERM, signal_handler) == SIG_ERR)
+    vWarn("Failed to install SIGTERM handler.");
+#endif
+}
+
+
 /** Returns true if there is already another Vidalia process running. */
 bool
 is_vidalia_running(QString pidfile)
@@ -65,6 +100,10 @@
   vNotice("Vidalia %1 using Qt %2").arg(Vidalia::version())
                                    .arg(QT_VERSION_STR);
 
+  /* Install a signal handler to clean up properly after a catching a 
+   * SIGINT or SIGTERM. */
+  install_signal_handler();
+
 #if defined(USE_MARBLE) && defined(Q_OS_WIN32)
   vApp->addLibraryPath(vApp->applicationDirPath() + "/plugins/qt");
 #endif