|
Gaudi Framework, version v21r11 |
| Home | Generated: 30 Sep 2010 |
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 | |
Definition at line 811 of file GaudiTest.py.
| 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 ########################################################################
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.