def stop(self, mode=None): """Terminate the process.""" if mode is None: mode = fixture_interface.TeardownMode.TERMINATE if mode == fixture_interface.TeardownMode.KILL: signal = self.pb.Signals.Value("KILL") elif mode == fixture_interface.TeardownMode.TERMINATE: signal = self.pb.Signals.Value("TERMINATE") elif mode == fixture_interface.TeardownMode.ABORT: signal = self.pb.Signals.Value("ABRT") else: raise errors.ProcessError( "Process wrapper given unrecognized teardown mode: " + mode.value) signal_process = self.pb.SignalProcess(ProcessID=self._id, signal=signal) val = self._stub.Signal(signal_process) JASPER_PIDS.discard(self.pid) if not val.success \ and "cannot signal a process that has terminated" not in val.text \ and "os: process already finished" not in val.text: raise OSError( "Failed to signal Jasper process with pid {}: {}".format( self.pid, val.text))
def stop(self, mode=None): # pylint: disable=too-many-branches """Terminate the process.""" if mode is None: mode = fixture_interface.TeardownMode.TERMINATE if sys.platform == "win32": # Attempt to cleanly shutdown mongod. if mode != fixture_interface.TeardownMode.KILL and self.args and self.args[ 0].find("mongod") != -1: mongo_signal_handle = None try: mongo_signal_handle = win32event.OpenEvent( win32event.EVENT_MODIFY_STATE, False, "Global\\Mongo_" + str(self._process.pid)) if not mongo_signal_handle: # The process has already died. return win32event.SetEvent(mongo_signal_handle) # Wait 60 seconds for the program to exit. status = win32event.WaitForSingleObject( self._process._handle, 60 * 1000) if status == win32event.WAIT_OBJECT_0: return except win32process.error as err: # ERROR_FILE_NOT_FOUND (winerror=2) # ERROR_ACCESS_DENIED (winerror=5) # ERROR_INVALID_HANDLE (winerror=6) # One of the above errors is received if the process has # already died. if err.winerror not in (2, 5, 6): raise finally: win32api.CloseHandle(mongo_signal_handle) print("Failed to cleanly exit the program, calling TerminateProcess() on PID: " +\ str(self._process.pid)) # Adapted from implementation of Popen.terminate() in subprocess.py of Python 2.7 # because earlier versions do not catch exceptions. try: # Have the process exit with code 0 if it is terminated by us to simplify the # success-checking logic later on. win32process.TerminateProcess(self._process._handle, 0) except win32process.error as err: # ERROR_ACCESS_DENIED (winerror=5) is received when the process # has already died. if err.winerror != winerror.ERROR_ACCESS_DENIED: raise return_code = win32process.GetExitCodeProcess( self._process._handle) if return_code == win32con.STILL_ACTIVE: raise else: try: if mode == fixture_interface.TeardownMode.KILL: self._process.kill() elif mode == fixture_interface.TeardownMode.TERMINATE: self._process.terminate() elif mode == fixture_interface.TeardownMode.ABORT: self._process.send_signal(mode.value) else: raise errors.ProcessError( "Process wrapper given unrecognized teardown mode: " + mode.value) except OSError as err: # ESRCH (errno=3) is received when the process has already died. if err.errno != 3: raise