| # Gaudi Framework, version v22r4 |

Home |  | Generated: Fri Sep 2 2011

Public Member Functions | Public Attributes | Private Member Functions | Private Attributes

# 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
| This is the interesting part: dump the stack trace to a file.

## Detailed Description

Definition at line 815 of file GaudiTest.py.

## Constructor & Destructor 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 816 of file GaudiTest.py.

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

## Member Function Documentation

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 954 of file GaudiTest.py.

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

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

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

Definition at line 835 of file GaudiTest.py.

    00836                                                :
    00837         """Copied from TimeoutExecutable to allow the re-implementation of
    00838            _HandleChild.
    00839         """
    00840         if sys.platform == "win32":
    00841             # In Windows 2000 (or later), we should use "jobs" by
    00842             # analogy with UNIX process groups.  However, that
    00843             # functionality is not (yet) provided by the Python Win32
    00844             # extensions.
    00845             return 0
    00846
            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 849 of file GaudiTest.py.

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

## Member Data Documentation

GaudiTest::GaudiFilterExecutable::__input`[private]`

Definition at line 821 of file GaudiTest.py.

GaudiTest::GaudiFilterExecutable::__monitor_pid`[private]`

Definition at line 850 of file GaudiTest.py.

GaudiTest::GaudiFilterExecutable::__monitor_thread`[private]`

This is the interesting part: dump the stack trace to a file.

Definition at line 853 of file GaudiTest.py.

GaudiTest::GaudiFilterExecutable::__timeout`[private]`

Definition at line 821 of file GaudiTest.py.

GaudiTest::GaudiFilterExecutable::stack_trace_file

Definition at line 821 of file GaudiTest.py.

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

- /afs/cern.ch/sw/Gaudi/releases/GAUDI/GAUDI_v22r4/GaudiPolicy/qmtest_classes/GaudiTest.py

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines