GaudiTest.GaudiFilterExecutable Class Reference
Inheritance diagram for GaudiTest.GaudiFilterExecutable:
Collaboration diagram for GaudiTest.GaudiFilterExecutable:

Public Member Functions

def __init__
 
def __init__
 

Public Attributes

 stack_trace_file
 

Private Member Functions

def __UseSeparateProcessGroupForChild (self)
 
def _HandleChild (self)
 Needs to replace the ones from RedirectedExecutable and TimeoutExecutable. More...
 
def __Monitor (self)
 
def __UseSeparateProcessGroupForChild (self)
 
def _HandleChild (self)
 Needs to replace the ones from RedirectedExecutable and TimeoutExecutable. More...
 
def __Monitor (self)
 

Private Attributes

 __input
 
 __timeout
 
 __monitor_pid
 
 __monitor_thread
 This is the interesting part: dump the stack trace to a file. More...
 

Detailed Description

Definition at line 906 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 907 of file GaudiTest.py.

907  def __init__(self, input, timeout = -1):
908  """Create a new 'Filter'.
909 
910  'input' -- The string containing the input to provide to the
911  child process.
912 
913  'timeout' -- As for 'TimeoutExecutable.__init__'."""
914 
915  super(GaudiFilterExecutable, self).__init__(input, timeout)
916  self.__input = input
917  self.__timeout = timeout
918  self.stack_trace_file = None
919  # Temporary file to pass the stack trace from one process to the other
920  # The file must be closed and reopened when needed to avoid conflicts
921  # between the processes
922  tmpf = tempfile.mkstemp()
923  os.close(tmpf[0])
924  self.stack_trace_file = tmpf[1] # remember only the name
925 
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 907 of file GaudiTest.py.

907  def __init__(self, input, timeout = -1):
908  """Create a new 'Filter'.
909 
910  'input' -- The string containing the input to provide to the
911  child process.
912 
913  'timeout' -- As for 'TimeoutExecutable.__init__'."""
914 
915  super(GaudiFilterExecutable, self).__init__(input, timeout)
916  self.__input = input
917  self.__timeout = timeout
918  self.stack_trace_file = None
919  # Temporary file to pass the stack trace from one process to the other
920  # The file must be closed and reopened when needed to avoid conflicts
921  # between the processes
922  tmpf = tempfile.mkstemp()
923  os.close(tmpf[0])
924  self.stack_trace_file = tmpf[1] # remember only the name
925 

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

1045  def __Monitor(self):
1046  """Code copied from FilterExecutable.
1047  Kill the child if the timeout expires.
1048 
1049  This function is run in the monitoring thread."""
1050 
1051  # The timeout may be expressed as a floating-point value
1052  # on UNIX, but it must be an integer number of
1053  # milliseconds when passed to WaitForSingleObject.
1054  timeout = int(self.__timeout * 1000)
1055  # Wait for the child process to terminate or for the
1056  # timer to expire.
1057  result = win32event.WaitForSingleObject(self._GetChildPID(),
1058  timeout)
1059  # If the timeout occurred, kill the child process.
1060  if result == win32con.WAIT_TIMEOUT:
1061  self.Kill()
1062 
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 1045 of file GaudiTest.py.

1045  def __Monitor(self):
1046  """Code copied from FilterExecutable.
1047  Kill the child if the timeout expires.
1048 
1049  This function is run in the monitoring thread."""
1050 
1051  # The timeout may be expressed as a floating-point value
1052  # on UNIX, but it must be an integer number of
1053  # milliseconds when passed to WaitForSingleObject.
1054  timeout = int(self.__timeout * 1000)
1055  # Wait for the child process to terminate or for the
1056  # timer to expire.
1057  result = win32event.WaitForSingleObject(self._GetChildPID(),
1058  timeout)
1059  # If the timeout occurred, kill the child process.
1060  if result == win32con.WAIT_TIMEOUT:
1061  self.Kill()
1062 
def GaudiTest.GaudiFilterExecutable.__UseSeparateProcessGroupForChild (   self)
private
Copied from TimeoutExecutable to allow the re-implementation of
   _HandleChild.

Definition at line 926 of file GaudiTest.py.

927  """Copied from TimeoutExecutable to allow the re-implementation of
928  _HandleChild.
929  """
930  if sys.platform == "win32":
931  # In Windows 2000 (or later), we should use "jobs" by
932  # analogy with UNIX process groups. However, that
933  # functionality is not (yet) provided by the Python Win32
934  # extensions.
935  return 0
936 
937  return self.__timeout >= 0 or self.__timeout == -2
def __UseSeparateProcessGroupForChild(self)
Definition: GaudiTest.py:926
def GaudiTest.GaudiFilterExecutable.__UseSeparateProcessGroupForChild (   self)
private
Copied from TimeoutExecutable to allow the re-implementation of
   _HandleChild.

Definition at line 926 of file GaudiTest.py.

927  """Copied from TimeoutExecutable to allow the re-implementation of
928  _HandleChild.
929  """
930  if sys.platform == "win32":
931  # In Windows 2000 (or later), we should use "jobs" by
932  # analogy with UNIX process groups. However, that
933  # functionality is not (yet) provided by the Python Win32
934  # extensions.
935  return 0
936 
937  return self.__timeout >= 0 or self.__timeout == -2
def __UseSeparateProcessGroupForChild(self)
Definition: GaudiTest.py:926
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 940 of file GaudiTest.py.

940  def _HandleChild(self):
941  """Code copied from both FilterExecutable and TimeoutExecutable.
942  """
943  # Close the pipe ends that we do not need.
944  if self._stdin_pipe:
945  self._ClosePipeEnd(self._stdin_pipe[0])
946  if self._stdout_pipe:
947  self._ClosePipeEnd(self._stdout_pipe[1])
948  if self._stderr_pipe:
949  self._ClosePipeEnd(self._stderr_pipe[1])
950 
951  # The pipes created by 'RedirectedExecutable' must be closed
952  # before the monitor process (created by 'TimeoutExecutable')
953  # is created. Otherwise, if the child process dies, 'select'
954  # in the parent will not return if the monitor process may
955  # still have one of the file descriptors open.
956 
957  super(qm.executable.TimeoutExecutable, self)._HandleChild()
958 
960  # Put the child into its own process group. This step is
961  # performed in both the parent and the child; therefore both
962  # processes can safely assume that the creation of the process
963  # group has taken place.
964  child_pid = self._GetChildPID()
965  try:
966  os.setpgid(child_pid, child_pid)
967  except:
968  # The call to setpgid may fail if the child has exited,
969  # or has already called 'exec'. In that case, we are
970  # guaranteed that the child has already put itself in the
971  # desired process group.
972  pass
973  # Create the monitoring process.
974  #
975  # If the monitoring process is in parent's process group and
976  # kills the child after waitpid has returned in the parent, we
977  # may end up trying to kill a process group other than the one
978  # that we intend to kill. Therefore, we put the monitoring
979  # process in the same process group as the child; that ensures
980  # that the process group will persist until the monitoring
981  # process kills it.
982  self.__monitor_pid = os.fork()
983  if self.__monitor_pid != 0:
984  # Make sure that the monitoring process is placed into the
985  # child's process group before the parent process calls
986  # 'waitpid'. In this way, we are guaranteed that the process
987  # group as the child
988  os.setpgid(self.__monitor_pid, child_pid)
989  else:
990  # Put the monitoring process into the child's process
991  # group. We know the process group still exists at
992  # this point because either (a) we are in the process
993  # group, or (b) the parent has not yet called waitpid.
994  os.setpgid(0, child_pid)
995 
996  # Close all open file descriptors. They are not needed
997  # in the monitor process. Furthermore, when the parent
998  # closes the write end of the stdin pipe to the child,
999  # we do not want the pipe to remain open; leaving the
1000  # pipe open in the monitor process might cause the child
1001  # to block waiting for additional input.
1002  try:
1003  max_fds = os.sysconf("SC_OPEN_MAX")
1004  except:
1005  max_fds = 256
1006  for fd in xrange(max_fds):
1007  try:
1008  os.close(fd)
1009  except:
1010  pass
1011  try:
1012  if self.__timeout >= 0:
1013  # Give the child time to run.
1014  time.sleep (self.__timeout)
1015  #######################################################
1016  ### This is the interesting part: dump the stack trace to a file
1017  if sys.platform == "linux2": # we should be have /proc and gdb
1018  cmd = ["gdb",
1019  os.path.join("/proc", str(child_pid), "exe"),
1020  str(child_pid),
1021  "-batch", "-n", "-x",
1022  "'%s'" % os.path.join(os.path.dirname(__file__), "stack-trace.gdb")]
1023  # FIXME: I wanted to use subprocess.Popen, but it doesn't want to work
1024  # in this context.
1025  o = os.popen(" ".join(cmd)).read()
1026  open(self.stack_trace_file,"w").write(o)
1027  #######################################################
1028 
1029  # Kill all processes in the child process group.
1030  os.kill(0, signal.SIGKILL)
1031  else:
1032  # This call to select will never terminate.
1033  select.select ([], [], [])
1034  finally:
1035  # Exit. This code is in a finally clause so that
1036  # we are guaranteed to get here no matter what.
1037  os._exit(0)
1038  elif self.__timeout >= 0 and sys.platform == "win32":
1039  # Create a monitoring thread.
1040  self.__monitor_thread = Thread(target = self.__Monitor)
1041  self.__monitor_thread.start()
1042 
def _HandleChild(self)
Needs to replace the ones from RedirectedExecutable and TimeoutExecutable.
Definition: GaudiTest.py:940
__monitor_thread
This is the interesting part: dump the stack trace to a file.
Definition: GaudiTest.py:1040
def __UseSeparateProcessGroupForChild(self)
Definition: GaudiTest.py:926
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 940 of file GaudiTest.py.

940  def _HandleChild(self):
941  """Code copied from both FilterExecutable and TimeoutExecutable.
942  """
943  # Close the pipe ends that we do not need.
944  if self._stdin_pipe:
945  self._ClosePipeEnd(self._stdin_pipe[0])
946  if self._stdout_pipe:
947  self._ClosePipeEnd(self._stdout_pipe[1])
948  if self._stderr_pipe:
949  self._ClosePipeEnd(self._stderr_pipe[1])
950 
951  # The pipes created by 'RedirectedExecutable' must be closed
952  # before the monitor process (created by 'TimeoutExecutable')
953  # is created. Otherwise, if the child process dies, 'select'
954  # in the parent will not return if the monitor process may
955  # still have one of the file descriptors open.
956 
957  super(qm.executable.TimeoutExecutable, self)._HandleChild()
958 
960  # Put the child into its own process group. This step is
961  # performed in both the parent and the child; therefore both
962  # processes can safely assume that the creation of the process
963  # group has taken place.
964  child_pid = self._GetChildPID()
965  try:
966  os.setpgid(child_pid, child_pid)
967  except:
968  # The call to setpgid may fail if the child has exited,
969  # or has already called 'exec'. In that case, we are
970  # guaranteed that the child has already put itself in the
971  # desired process group.
972  pass
973  # Create the monitoring process.
974  #
975  # If the monitoring process is in parent's process group and
976  # kills the child after waitpid has returned in the parent, we
977  # may end up trying to kill a process group other than the one
978  # that we intend to kill. Therefore, we put the monitoring
979  # process in the same process group as the child; that ensures
980  # that the process group will persist until the monitoring
981  # process kills it.
982  self.__monitor_pid = os.fork()
983  if self.__monitor_pid != 0:
984  # Make sure that the monitoring process is placed into the
985  # child's process group before the parent process calls
986  # 'waitpid'. In this way, we are guaranteed that the process
987  # group as the child
988  os.setpgid(self.__monitor_pid, child_pid)
989  else:
990  # Put the monitoring process into the child's process
991  # group. We know the process group still exists at
992  # this point because either (a) we are in the process
993  # group, or (b) the parent has not yet called waitpid.
994  os.setpgid(0, child_pid)
995 
996  # Close all open file descriptors. They are not needed
997  # in the monitor process. Furthermore, when the parent
998  # closes the write end of the stdin pipe to the child,
999  # we do not want the pipe to remain open; leaving the
1000  # pipe open in the monitor process might cause the child
1001  # to block waiting for additional input.
1002  try:
1003  max_fds = os.sysconf("SC_OPEN_MAX")
1004  except:
1005  max_fds = 256
1006  for fd in xrange(max_fds):
1007  try:
1008  os.close(fd)
1009  except:
1010  pass
1011  try:
1012  if self.__timeout >= 0:
1013  # Give the child time to run.
1014  time.sleep (self.__timeout)
1015  #######################################################
1016  ### This is the interesting part: dump the stack trace to a file
1017  if sys.platform == "linux2": # we should be have /proc and gdb
1018  cmd = ["gdb",
1019  os.path.join("/proc", str(child_pid), "exe"),
1020  str(child_pid),
1021  "-batch", "-n", "-x",
1022  "'%s'" % os.path.join(os.path.dirname(__file__), "stack-trace.gdb")]
1023  # FIXME: I wanted to use subprocess.Popen, but it doesn't want to work
1024  # in this context.
1025  o = os.popen(" ".join(cmd)).read()
1026  open(self.stack_trace_file,"w").write(o)
1027  #######################################################
1028 
1029  # Kill all processes in the child process group.
1030  os.kill(0, signal.SIGKILL)
1031  else:
1032  # This call to select will never terminate.
1033  select.select ([], [], [])
1034  finally:
1035  # Exit. This code is in a finally clause so that
1036  # we are guaranteed to get here no matter what.
1037  os._exit(0)
1038  elif self.__timeout >= 0 and sys.platform == "win32":
1039  # Create a monitoring thread.
1040  self.__monitor_thread = Thread(target = self.__Monitor)
1041  self.__monitor_thread.start()
1042 
def _HandleChild(self)
Needs to replace the ones from RedirectedExecutable and TimeoutExecutable.
Definition: GaudiTest.py:940
__monitor_thread
This is the interesting part: dump the stack trace to a file.
Definition: GaudiTest.py:1040
def __UseSeparateProcessGroupForChild(self)
Definition: GaudiTest.py:926

Member Data Documentation

GaudiTest.GaudiFilterExecutable.__input
private

Definition at line 916 of file GaudiTest.py.

GaudiTest.GaudiFilterExecutable.__monitor_pid
private

Definition at line 982 of file GaudiTest.py.

GaudiTest.GaudiFilterExecutable.__monitor_thread
private

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

Definition at line 1040 of file GaudiTest.py.

GaudiTest.GaudiFilterExecutable.__timeout
private

Definition at line 917 of file GaudiTest.py.

GaudiTest.GaudiFilterExecutable.stack_trace_file

Definition at line 918 of file GaudiTest.py.


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