PATCH: Improve handling of SIGTERM and SIGINT

Mark Mitchell mark at codesourcery.com
Mon Aug 11 22:55:56 UTC 2003


This patch restores the correct handling of SIGINT (namely,
termination of QMTest) and adds similar behavior for SIGTERM.

--
Mark Mitchell
CodeSourcery, LLC
mark at codesourcery.com

2003-08-11  Mark Mitchell  <mark at codesourcery.com>

	* qm/platform_unix.py (SignalException.__init__): Tweak message
	formatting.
	(_initialize): Tidy.
	* qm/test/execution_engine.py (ExecutionEngine._RunTests): Honor
	termination requests.
	* qm/test/target.py: Import qm.platform and signal.
	(Target.RunTest): Honor temination requests in the form of
	SIGTERM.

Index: qm/platform_unix.py
===================================================================
RCS file: /home/sc/Repository/qm/qm/platform_unix.py,v
retrieving revision 1.12
diff -c -5 -p -r1.12 platform_unix.py
*** qm/platform_unix.py	9 May 2003 22:17:44 -0000	1.12
--- qm/platform_unix.py	11 Aug 2003 22:52:24 -0000
*************** class SignalException(common.QMException
*** 56,66 ****
          """Create a new signal exception.
  
          'signal_number' -- The signal number."""
  
          # Construct a text argument for the exception.
!         message = "signal %d" % signal_number
          # Include the signal name, if available.
          signal_name = get_signal_name(signal_number)
          if signal_name is not None:
              message = message + " (%s)" % signal_name
          # Initialize the base class.
--- 56,66 ----
          """Create a new signal exception.
  
          'signal_number' -- The signal number."""
  
          # Construct a text argument for the exception.
!         message = "Signal %d" % signal_number
          # Include the signal name, if available.
          signal_name = get_signal_name(signal_number)
          if signal_name is not None:
              message = message + " (%s)" % signal_name
          # Initialize the base class.
*************** def get_host_name():
*** 274,292 ****
  
  def _initialize():
      """Perform module initialization."""
  
      # Install signal handlers for several common signals.
!     map(install_signal_handler,
!         [
!         signal.SIGALRM,
!         signal.SIGHUP,
!         signal.SIGTERM,
!         signal.SIGUSR1,
!         signal.SIGUSR2,
!         ])
!         
  
  _initialize()
  
  ########################################################################
  # Local Variables:
--- 274,289 ----
  
  def _initialize():
      """Perform module initialization."""
  
      # Install signal handlers for several common signals.
!     for s in (signal.SIGALRM,
!               signal.SIGHUP,
!               signal.SIGTERM,
!               signal.SIGUSR1,
!               signal.SIGUSR2):
!         install_signal_handler(s)
  
  _initialize()
  
  ########################################################################
  # Local Variables:
Index: qm/test/execution_engine.py
===================================================================
RCS file: /home/sc/Repository/qm/qm/test/execution_engine.py,v
retrieving revision 1.23
diff -c -5 -p -r1.23 execution_engine.py
*** qm/test/execution_engine.py	7 Aug 2003 17:05:20 -0000	1.23
--- qm/test/execution_engine.py	11 Aug 2003 22:52:24 -0000
*************** class ExecutionEngine:
*** 339,349 ****
          self.__patterns = {}
          # A map from target patterns to lists of test descriptors ready
          # to run.
          self.__target_pattern_queues = {}
          
!         while self.__num_tests_started < num_tests:
              # Process any responses and update the count of idle targets.
              while self.__CheckForResponse(wait=0):
                  pass
  
              # Now look for idle targets.
--- 339,350 ----
          self.__patterns = {}
          # A map from target patterns to lists of test descriptors ready
          # to run.
          self.__target_pattern_queues = {}
          
!         while (self.__num_tests_started < num_tests
!                and not self.IsTerminationRequested()):
              # Process any responses and update the count of idle targets.
              while self.__CheckForResponse(wait=0):
                  pass
  
              # Now look for idle targets.
Index: qm/test/target.py
===================================================================
RCS file: /home/sc/Repository/qm/qm/test/target.py,v
retrieving revision 1.20
diff -c -5 -p -r1.20 target.py
*** qm/test/target.py	9 May 2003 22:17:44 -0000	1.20
--- qm/test/target.py	11 Aug 2003 22:52:24 -0000
***************
*** 17,30 ****
--- 17,32 ----
  # imports
  ########################################################################
  
  import qm
  import qm.extension
+ import qm.platform
  from   qm.test.context import *
  from   qm.test.result import *
  from   qm.test.database import NoSuchResourceError
  import re
+ import signal
  import sys
  
  ########################################################################
  # classes
  ########################################################################
*************** class Target(qm.extension.Extension):
*** 204,219 ****
              # Set up any required resources.
              self.__SetUpResources(descriptor, context)
              # Run the test.
              descriptor.Run(context, result)
          except KeyboardInterrupt:
!             result.NoteException(cause = "Interrupted.")
              # We received a KeyboardInterrupt, indicating that the
              # user would like to exit QMTest.  Ask the execution
              # engine to stop.
              if self.__engine:
                  self.__engine.RequestTermination()
          except self.__ResourceSetUpException, e:
              result.SetOutcome(Result.UNTESTED)
              result[Result.CAUSE] = qm.message("failed resource")
              result[Result.RESOURCE] = e.resource
          except:
--- 206,235 ----
              # Set up any required resources.
              self.__SetUpResources(descriptor, context)
              # Run the test.
              descriptor.Run(context, result)
          except KeyboardInterrupt:
!             result.NoteException(cause = "Interrupted by user.")
              # We received a KeyboardInterrupt, indicating that the
              # user would like to exit QMTest.  Ask the execution
              # engine to stop.
              if self.__engine:
                  self.__engine.RequestTermination()
+         except qm.platform.SignalException, e:
+             # Note the exception.
+             result.NoteException(cause = str(e))
+             # If we get a SIGTERM, propagate it so that QMTest
+             # terminates.
+             if e.GetSignalNumber() == signal.SIGTERM:
+                 # Record the result so that the traceback is
+                 # available.
+                 self._RecordResult(result)
+                 # Ask the execution engine to stop running tests.
+                 if self.__engine:
+                     self.__engine.RequestTermination()
+                 # Re-raise the exception.
+                 raise
          except self.__ResourceSetUpException, e:
              result.SetOutcome(Result.UNTESTED)
              result[Result.CAUSE] = qm.message("failed resource")
              result[Result.RESOURCE] = e.resource
          except:



More information about the qmtest mailing list