Gaudi Framework, version v21r11

Home   Generated: 30 Sep 2010

GaudiTest::GaudiFilterExecutable Class Reference

List of all members.

Public Member Functions

def __init__

Public Attributes

 stack_trace_file

Private Member Functions

def __UseSeparateProcessGroupForChild
def _HandleChild
 Needs to replace the ones from RedirectedExecutable and TimeoutExecutable.
def __Monitor

Private Attributes

 __input
 __timeout
 __monitor_pid
 __monitor_thread


Detailed Description

Definition at line 811 of file GaudiTest.py.


Member Function Documentation

def GaudiTest::GaudiFilterExecutable::__init__ (   self,
  input,
  timeout = -1 
)

Create a new 'Filter'.

'input' -- The string containing the input to provide to the
child process.

'timeout' -- As for 'TimeoutExecutable.__init__'.

Definition at line 812 of file GaudiTest.py.

00812                                            :
00813         """Create a new 'Filter'.
00814 
00815         'input' -- The string containing the input to provide to the
00816         child process.
00817 
00818         'timeout' -- As for 'TimeoutExecutable.__init__'."""
00819 
00820         super(GaudiFilterExecutable, self).__init__(input, timeout)
00821         self.__input = input
00822         self.__timeout = timeout
00823         self.stack_trace_file = None
00824         # Temporary file to pass the stack trace from one process to the other
00825         # The file must be closed and reopened when needed to avoid conflicts
00826         # between the processes
00827         tmpf = tempfile.mkstemp()
00828         os.close(tmpf[0])
00829         self.stack_trace_file = tmpf[1] # remember only the name
00830 
    def __UseSeparateProcessGroupForChild(self):

def GaudiTest::GaudiFilterExecutable::__UseSeparateProcessGroupForChild (   self  )  [private]

Copied from TimeoutExecutable to allow the re-implementation of
   _HandleChild.

Definition at line 831 of file GaudiTest.py.

00831                                                :
00832         """Copied from TimeoutExecutable to allow the re-implementation of
00833            _HandleChild.
00834         """
00835         if sys.platform == "win32":
00836             # In Windows 2000 (or later), we should use "jobs" by
00837             # analogy with UNIX process groups.  However, that
00838             # functionality is not (yet) provided by the Python Win32
00839             # extensions.
00840             return 0
00841 
00842         return self.__timeout >= 0 or self.__timeout == -2
    ##

def GaudiTest::GaudiFilterExecutable::_HandleChild (   self  )  [private]

Needs to replace the ones from RedirectedExecutable and TimeoutExecutable.

Code copied from both FilterExecutable and TimeoutExecutable.

Definition at line 845 of file GaudiTest.py.

00845                           :
00846         """Code copied from both FilterExecutable and TimeoutExecutable.
00847         """
00848         # Close the pipe ends that we do not need.
00849         if self._stdin_pipe:
00850             self._ClosePipeEnd(self._stdin_pipe[0])
00851         if self._stdout_pipe:
00852             self._ClosePipeEnd(self._stdout_pipe[1])
00853         if self._stderr_pipe:
00854             self._ClosePipeEnd(self._stderr_pipe[1])
00855 
00856         # The pipes created by 'RedirectedExecutable' must be closed
00857         # before the monitor process (created by 'TimeoutExecutable')
00858         # is created.  Otherwise, if the child process dies, 'select'
00859         # in the parent will not return if the monitor process may
00860         # still have one of the file descriptors open.
00861 
00862         super(qm.executable.TimeoutExecutable, self)._HandleChild()
00863 
00864         if self.__UseSeparateProcessGroupForChild():
00865             # Put the child into its own process group.  This step is
00866             # performed in both the parent and the child; therefore both
00867             # processes can safely assume that the creation of the process
00868             # group has taken place.
00869             child_pid = self._GetChildPID()
00870             try:
00871                 os.setpgid(child_pid, child_pid)
00872             except:
00873                 # The call to setpgid may fail if the child has exited,
00874                 # or has already called 'exec'.  In that case, we are
00875                 # guaranteed that the child has already put itself in the
00876                 # desired process group.
00877                 pass
00878             # Create the monitoring process.
00879             #
00880             # If the monitoring process is in parent's process group and
00881             # kills the child after waitpid has returned in the parent, we
00882             # may end up trying to kill a process group other than the one
00883             # that we intend to kill.  Therefore, we put the monitoring
00884             # process in the same process group as the child; that ensures
00885             # that the process group will persist until the monitoring
00886             # process kills it.
00887             self.__monitor_pid = os.fork()
00888             if self.__monitor_pid != 0:
00889                 # Make sure that the monitoring process is placed into the
00890                 # child's process group before the parent process calls
00891                 # 'waitpid'.  In this way, we are guaranteed that the process
00892                 # group as the child
00893                 os.setpgid(self.__monitor_pid, child_pid)
00894             else:
00895                 # Put the monitoring process into the child's process
00896                 # group.  We know the process group still exists at
00897                 # this point because either (a) we are in the process
00898                 # group, or (b) the parent has not yet called waitpid.
00899                 os.setpgid(0, child_pid)
00900 
00901                 # Close all open file descriptors.  They are not needed
00902                 # in the monitor process.  Furthermore, when the parent
00903                 # closes the write end of the stdin pipe to the child,
00904                 # we do not want the pipe to remain open; leaving the
00905                 # pipe open in the monitor process might cause the child
00906                 # to block waiting for additional input.
00907                 try:
00908                     max_fds = os.sysconf("SC_OPEN_MAX")
00909                 except:
00910                     max_fds = 256
00911                 for fd in xrange(max_fds):
00912                     try:
00913                         os.close(fd)
00914                     except:
00915                         pass
00916                 try:
00917                     if self.__timeout >= 0:
00918                         # Give the child time to run.
00919                         time.sleep (self.__timeout)
00920                         #######################################################
00921                         ### This is the interesting part: dump the stack trace to a file
00922                         if sys.platform == "linux2": # we should be have /proc and gdb
00923                             cmd = ["gdb",
00924                                    os.path.join("/proc", str(child_pid), "exe"),
00925                                    str(child_pid),
00926                                    "-batch", "-n", "-x",
00927                                    "'%s'" % os.path.join(os.path.dirname(__file__), "stack-trace.gdb")]
00928                             # FIXME: I wanted to use subprocess.Popen, but it doesn't want to work
00929                             #        in this context.
00930                             o = os.popen(" ".join(cmd)).read()
00931                             open(self.stack_trace_file,"w").write(o)
00932                         #######################################################
00933 
00934                         # Kill all processes in the child process group.
00935                         os.kill(0, signal.SIGKILL)
00936                     else:
00937                         # This call to select will never terminate.
00938                         select.select ([], [], [])
00939                 finally:
00940                     # Exit.  This code is in a finally clause so that
00941                     # we are guaranteed to get here no matter what.
00942                     os._exit(0)
00943         elif self.__timeout >= 0 and sys.platform == "win32":
00944             # Create a monitoring thread.
00945             self.__monitor_thread = Thread(target = self.__Monitor)
00946             self.__monitor_thread.start()
00947 
    if sys.platform == "win32":

def GaudiTest::GaudiFilterExecutable::__Monitor (   self  )  [private]

Code copied from FilterExecutable.
Kill the child if the timeout expires.

This function is run in the monitoring thread.

Definition at line 950 of file GaudiTest.py.

00950                            :
00951             """Code copied from FilterExecutable.
00952             Kill the child if the timeout expires.
00953 
00954             This function is run in the monitoring thread."""
00955 
00956             # The timeout may be expressed as a floating-point value
00957             # on UNIX, but it must be an integer number of
00958             # milliseconds when passed to WaitForSingleObject.
00959             timeout = int(self.__timeout * 1000)
00960             # Wait for the child process to terminate or for the
00961             # timer to expire.
00962             result = win32event.WaitForSingleObject(self._GetChildPID(),
00963                                                     timeout)
00964             # If the timeout occurred, kill the child process.
00965             if result == win32con.WAIT_TIMEOUT:
00966                 self.Kill()
00967 
########################################################################


Member Data Documentation

Definition at line 821 of file GaudiTest.py.

Definition at line 822 of file GaudiTest.py.

Definition at line 823 of file GaudiTest.py.

Definition at line 887 of file GaudiTest.py.

Definition at line 945 of file GaudiTest.py.


The documentation for this class was generated from the following file:

Generated at Thu Sep 30 09:59:02 2010 for Gaudi Framework, version v21r11 by Doxygen version 1.5.6 written by Dimitri van Heesch, © 1997-2004