def verify(self, retcode, timeout, stdout, stderr): """This verifies that the correct command is attributed.""" if getattr(self, "_timed_out", False): raise ProcessTimedOut( "Process did not terminate within %s seconds" % (timeout, ), getattr(self, "argv", None)) if retcode is not None: if hasattr(retcode, "__contains__"): if self.returncode not in retcode: raise ProcessExecutionError(getattr(self, "argv", None), self.returncode, stdout, stderr) elif self.returncode != retcode: raise ProcessExecutionError(getattr(self, "argv", None), self.returncode, stdout, stderr)
def posix_daemonize(command, cwd, stdout=None, stderr=None, append=True): if stdout is None: stdout = os.devnull if stderr is None: stderr = stdout MAX_SIZE = 16384 rfd, wfd = os.pipe() argv = command.formulate() firstpid = os.fork() if firstpid == 0: # first child: become session leader, os.close(rfd) rc = 0 try: os.setsid() os.umask(0) stdin = open(os.devnull) stdout = open(stdout, "a" if append else "w") stderr = open(stderr, "a" if append else "w") signal.signal(signal.SIGHUP, signal.SIG_IGN) proc = command.popen( cwd=cwd, close_fds=True, stdin=stdin.fileno(), stdout=stdout.fileno(), stderr=stderr.fileno(), ) os.write(wfd, str(proc.pid).encode("utf8")) except Exception: rc = 1 tbtext = "".join( traceback.format_exception(*sys.exc_info()))[-MAX_SIZE:] os.write(wfd, tbtext.encode("utf8")) finally: os.close(wfd) os._exit(rc) else: # wait for first child to die os.close(wfd) _, rc = os.waitpid(firstpid, 0) output = os.read(rfd, MAX_SIZE) os.close(rfd) try: output = output.decode("utf8") except UnicodeError: pass if rc == 0 and output.isdigit(): secondpid = int(output) else: raise ProcessExecutionError(argv, rc, "", output) proc = subprocess.Popen.__new__(subprocess.Popen) proc._child_created = True proc.returncode = None proc.stdout = None proc.stdin = None proc.stderr = None proc.pid = secondpid proc.universal_newlines = False proc._input = None proc._waitpid_lock = _fake_lock() proc._communication_started = False proc.args = argv proc.argv = argv def poll(self=proc): if self.returncode is None: try: os.kill(self.pid, 0) except OSError: ex = sys.exc_info()[1] if ex.errno == errno.ESRCH: # process does not exist self.returncode = 0 else: raise return self.returncode def wait(self=proc): while self.returncode is None: if self.poll() is None: time.sleep(0.5) return proc.returncode proc.poll = poll proc.wait = wait return proc
def test_no_tag(): scm = Scm('/foo') scm._git = MagicMock(side_effect=ProcessExecutionError([], 1, '!', '!')) assert scm.tag == None