def on_finish(self): if self._fd is not None: os.close(self._fd) if self._pid is not None: os.kill(self._pid, signal.SIGKILL) # TODO: signalfd os.wait4(self._pid, 0)
def _wait_for_process(self, pid, name): """Wait for the given process to terminate. @return tuple of exit code and resource usage """ try: logging.debug("Waiting for process %s with pid %s", name, pid) unused_pid, exitcode, ru_child = os.wait4(pid, 0) return exitcode, ru_child except OSError as e: if self.PROCESS_KILLED and e.errno == errno.EINTR: # Interrupted system call seems always to happen # if we killed the process ourselves after Ctrl+C was pressed # We can try again to get exitcode and resource usage. logging.debug( "OSError %s while waiting for termination of %s (%s): %s.", e.errno, name, pid, e.strerror) try: unused_pid, exitcode, ru_child = os.wait4(pid, 0) return exitcode, ru_child except OSError: pass # original error will be handled and this ignored logging.critical( "OSError %s while waiting for termination of %s (%s): %s.", e.errno, name, pid, e.strerror) return (0, None)
def set_rsa(host, rsa_pub, user, password): """ logs into system via ssh and appends to authorized_keys using username password :param host: name over the server :param rsa_pub: absolute path to your id_rsa.pub :param user: host login creds :param password: host login creds :param home_dir: home directory for user """ output = None with open(rsa_pub, 'r') as file: output = file.read() cmd = '/bin/mkdir -p /root/.ssh && echo "%s" >>' ' /root/.ssh/authorized_keys &&' ' /bin/chmod -R 600 /root/.ssh' % (output.strip()) pid, fd = pty.fork() if pid == 0: os.execvp("/usr/bin/ssh", ["ssh", user+'@'+host, '-o', 'NumberOfPasswordPrompts=1', '-o', 'StrictHostKeyChecking=no', '-o', 'UserKnownHostsFile=/dev/null', cmd]) elif pid > 0: searches = {'password': password, 'continue connecting': 'yes'} if event(fd, searches) == 'continue connecting': event(fd, searches) os.wait4(pid, 0) os.close(fd)
def set_rsa(host, rsa_pub, user, password): """ logs into system via ssh and appends to authorized_keys using username password @param host: name over the server @param rsa_pub: absolute path to your id_rsa.pub @param user: host login creds @param password: host login creds @param home_dir: home directory for user """ output = None with open(rsa_pub, 'r') as file: output = file.read() print output cmd = '/bin/mkdir -p /root/.ssh && echo "%s" >> /root/.ssh/authorized_keys && /bin/chmod -R 600 /root/.ssh' % ( output.strip()) pid, fd = pty.fork() if pid == 0: os.execvp("/usr/bin/ssh", [ "ssh", user + '@' + host, '-o', 'NumberOfPasswordPrompts=1', '-o', 'StrictHostKeyChecking=no', '-o', 'UserKnownHostsFile=/dev/null', cmd ]) elif pid > 0: searches = {'password': password, 'continue connecting': 'yes'} if event(fd, searches) == 'continue connecting': event(fd, searches) os.wait4(pid, 0) os.close(fd)
def main(): os.mkdir('./csv') fname = "benchmarks.csv" # CSV with the averages with open('csv/' + fname, 'w+') as csvwritefile: writer = csv.writer(csvwritefile, quoting=csv.QUOTE_MINIMAL) writer.writerow([ 'Algorithm', 'Heuristics', 'w1', 'w2', 'Run Time', 'Path Length', 'Cost/Optimal', 'Nodes Expanded', 'Memory Used' ]) s_paths = np.zeros([5, 10]) a_star_admissible = partial(a_star, heuristic=manhattan_distance_a) for name, hs, w1, w2, a in algorithms(): for map_num in range(1, 6): for sg_pair in range(0, 10): (grid, start, goal) = input_file(map_path(map_num, sg_pair)) s_path = s_paths[map_num - 1, sg_pair] if s_path == 0: # Lazily create shortest paths for f, g, h, bp, s in uniform_cost_search( grid, grid[start], grid[goal]): pass s_paths[map_num - 1, sg_pair] = s_path = path_cost(grid, bp, s) algo = partial(a, grid, grid[start], grid[goal]) print("Forking to run {0}".format(name)) newpid = os.fork( ) # Fork the process so we get a separate memory footprint if newpid is 0: benchmarks = run_algo(algo, grid, s_path) with open( 'csv/' + name + str(hs) + str(w1) + str(w2) + '.csv', 'a') as csvfile: writer = csv.writer(csvfile, delimiter=' ', quotechar='|', quoting=csv.QUOTE_MINIMAL) writer.writerow(list(benchmarks)) os._exit(0) else: os.wait4(newpid, 0) with open('csv/' + fname, 'a') as csvwritefile: with open('csv/' + name + str(hs) + str(w1) + str(w2) + '.csv', 'r') as csvreadfile: # reader = csv.reader(csvreadfile, quoting=csv.QUOTE_MINIMAL) writer = csv.writer(csvwritefile, quoting=csv.QUOTE_MINIMAL) m = np.genfromtxt(csvreadfile, dtype='float', delimiter=' ') # m = np.array([r for r in reader]) row = [name, hs, w1, w2] for c in m.T: row.append(np.mean(c)) writer.writerow(row)
def _do_get_status(self, kill_reason): # if the process is already terminated, return the cached info if self.termination_info is not None: return self.termination_info self._wait_for_interruptible() # first send SIGSTOP to stop the process self.os_process.send_signal(signal.SIGSTOP) # then, use wait to get rusage struct (see man getrusage(2)) _, exit_status, rusage = os.wait4(self.os_process.pid, os.WUNTRACED) maxrss = rusage.ru_maxrss * 1024 termination_message = self._get_process_termination_message( exit_status) running = termination_message is None if running: error = f"running normally" if kill_reason is not None: error += f", killed because: {kill_reason}" else: error = termination_message if running: self._reset_maxrss() rss = self._read_stat_resource_usage() else: rss = 0 info = SandboxProcessInfo( peak_memory_usage=maxrss, current_memory_usage=rss, time_usage=rusage.ru_utime, error=error, ) if running: if kill_reason is not None: logging.debug(f"killing process because {kill_reason}") self.os_process.send_signal(signal.SIGKILL) os.wait4(self.os_process.pid, 0) self.termination_info = info else: # if process is not terminated, restart it with a SIGCONT self.os_process.send_signal(signal.SIGCONT) else: self.termination_info = info return info
def _compile_code(self, command, task_dir, lang, code): filename, compile_cmd, _ = command pid = os.fork() if pid == 0: resource.setrlimit(resource.RLIMIT_FSIZE, (self.target_file_size * 1.5,) * 2) if lang != 'JAVA': resource.setrlimit(resource.RLIMIT_AS, (self.memory_upper_bound,) * 2) os.chdir(task_dir) redirect_std_stream(False, True, True) with open(filename, 'w+') as f: f.write(code) try: os.execl(compile_cmd[0], *compile_cmd) finally: os.kill(os.getpid(), signal.SIGUSR1) elif pid > 0: _, status, usage = os.wait4(pid, 0) if os.WIFEXITED(status) and os.WEXITSTATUS(status) != 0: return False if os.WIFSIGNALED(status): if os.WTERMSIG(status) == signal.SIGUSR1: return False else: return False if get_file_size(os.path.join(task_dir, filename)) > self.target_file_size: return False return True else: raise JudgeSystemError()
def wait(self): """Wait for child process to terminate and records resource usage. Returns returncode attribute.""" if self.returncode is None: try: pid, sts, self.rusage = os.wait4(self.pid, 0) self.waittime = time.time() except OSError as e: if e.errno == errno.EINTR: # interrupted by signal handler, and it did the wait for us if self.returncode is not None: sts = None elif e.errno != errno.ECHILD: # This happens if SIGCHLD is set to be ignored or waiting # for child processes has otherwise been disabled for our # process. This child is dead, we can't get the status. sts = 0 else: raise if sts is not None: self._handle_exitstatus(sts) try: del self.registry[self.pid] except KeyError: pass return self.returncode
def test_failing_child_initialized_hook(self): def child_initialized_hook(child_pid): raise Exception, "child_initialized hook raises exception" # When child_initialized hook fails parent process will # exit. To test a failing initilization hook we fork and watch # the new child. pid = os.fork() if not pid: event_hooks = {"child_initialized" : child_initialized_hook} with testing.no_stderr(): # This will fail. redirecting stderr to /dev/null will # silence the test output. self.run_child_function_in_catbox(event_hooks=event_hooks) else: status = 0 wait_pid = 0 try: for _ in range(5): (wait_pid, status, _) = os.wait4(pid, os.WNOHANG) if wait_pid == pid: break time.sleep(.1) except OSError, e: T.assert_in("No child processes", e) else:
def wait4(pid, options): """ Wait for completion of a given child process. Returns the pid of the completed child process, it's rusage, and it's exit status code split into a ``tuple`` which includes the processes exit code, the signal responsible for the processes termination, and whether or not the process left a core dump behind. If there was no exit code then the first value will be ``None``, and if there was no signal, then the second value will be ``None``. If ``pid`` is greater than `0`, ``waitpid()`` requests status information for that specific process. If ``pid`` is ``0``, the request is for the status of any child in the process group of the current process. If ``pid`` is ``-1``, the request pertains to any child of the current process. If ``pid`` is less than ``-1``, status is requested for any process in the process group ``-pid`` (the absolute value of ``pid``). >>> pid = os.spawnlp(os.P_NOWAIT, 'true', 'true') >>> wait4(pid, 0) # doctest: +ELLIPSIS Status(pid=..., exit=0, signal=None, core=False, rusage=...) :param pid: pid to wait for :type pid: ``int`` :param options: options for wait :type options: ``int`` :returns: ``5-tuple`` (pid, exit, signal, core, rusage) :rtype: ``5-tuple`` """ pid, status, rusage = os.wait4(pid, options) exit_, signal, core = split(status) return PRStatus(pid, exit_, signal, core, rusage)
def play_workload(host, port, workload, quiet=False): metric = {} if quiet: with open(os.devnull, 'w') as devnull: load_workload = subprocess.Popen([ "mongo-tcp-replay/mongo-tcp-replay", "-mongodHost", host, "-mongodPort", port, "-pcapFile", workload ], stdout=devnull) else: f = open("sniff.out", 'w+') load_workload = subprocess.Popen([ "mongosniff", "--source", "FILE", workload, "--forward", host + ":" + port ], stdout=f) f.close() # Get the resource usage of the workload ru = os.wait4(load_workload.pid, 0)[2] workload_time = ru.ru_utime + ru.ru_stime metric['workload_time'] = workload_time return metric
def run_command_proc_not_working(cmd): #... missing argument # https://sources.debian.org/src/time/1.7-25.1/time.c/ pid = os.fork() if pid < 0: exit("cannot fork") elif 0 == pid: # If child. # Don't cast execvp arguments; that causes errors on some systems, # versus merely warnings if the cast is left off. os.execvp(cmd[0], cmd) # error (0, errno, "cannot run %s", cmd[0]); os._exit(126) # errno == ENOENT ? 127 : 126 print('ppid:_' + str(os.getpid()) + '_') print('pid:__' + str(pid) + '_') pcmdlinef = open('/proc/' + str(os.getpid()) + '/cmdline', 'r') cmdlinef = open('/proc/' + str(pid) + '/cmdline', 'r') # This is not from time.c statusf = open('/proc/' + str(pid) + '/status', 'r') iof = open('/proc/' + str(pid) + '/io', 'r') print(pcmdlinef.read()) print(cmdlinef.read()) print('*') subprocess.run(["cat", '/proc/' + str(os.getpid()) + '/cmdline']) print() subprocess.run(["cat", '/proc/' + str(pid) + '/cmdline']) print() print(os.wait4(pid, 0)) print("Child just terminated.")
def main(): args = get_options() if args.show_id: show_current_users_and_groups() sys.exit(0) mamaji_data = fetch_mamaji_data(args) filter_options(mamaji_data) target_cmd = None if args.cmd: target_cmd = args.cmd if not args.do_fork: change_users_and_groups(mamaji_data) # if target_cmd is None, do nothing if target_cmd: os.execlp(target_cmd[0], *target_cmd) sys.exit(0) if args.do_fork and not args.cmd: target_cmd = [find_shell()] pid = os.fork() if pid == -1: warn('failed to do fork') sys.exit(1) elif pid == 0: change_users_and_groups(mamaji_data) os.execlp(target_cmd[0], *target_cmd) else: status = os.wait4(pid, 0)[1] >> 8 sys.exit(status)
def wait4(self): """ Wait for child process to terminate. Returns returncode attribute.""" while self.returncode is None: try: (pid, sts, rusage) = os.wait4(self.pid, 0) self.rusage = rusage except OSError as exc: if exc.errno != errno.ECHILD: raise # This happens if SIGCLD is set to be ignored or waiting # for child processes has otherwise been disabled for our # process. This child is dead, we can't get the status. pid = self.pid sts = 0 # Check the pid and loop as waitpid has been known to return # 0 even without WNOHANG in odd situations. issue14396. if pid == self.pid: self._handle_exitstatus(sts) else: try: _ = psutil.Process(self.pid) except psutil.NoSuchProcess: print 'Process finished but wait4() returned a mismatched pid' self.returncode = 1 if self.returncode == -signal.SIGSEGV: print "SEGMENTATION FAULT" return self.returncode
def test_failing_child_initialized_hook(self): def child_initialized_hook(child_pid): raise Exception("child_initialized hook raises exception") # When child_initialized hook fails parent process will # exit. To test a failing initilization hook we fork and watch # the new child. pid = os.fork() if not pid: event_hooks = {"child_initialized": child_initialized_hook} with testing.no_stderr(): # This will fail. redirecting stderr to /dev/null will # silence the test output. self.run_child_function_in_catbox(event_hooks=event_hooks) else: status = 0 wait_pid = 0 try: for _ in range(5): (wait_pid, status, _) = os.wait4(pid, os.WNOHANG) if wait_pid == pid: break time.sleep(.1) except OSError as e: T.assert_in("No child processes", e) else: T.assert_not_equal( status, 0, "Failing child_initialized hook did not make parent exit")
def watchRunProgram(self, pid): usingMem = 0 while True: wpid, status, res = os.wait4(pid,0) signal.signal(signal.SIGXCPU, self.sigHandler) # 정상 종료된 경우 if os.WIFEXITED(status): return 'Grading', res[0], usingMem exitCode = os.WEXITSTATUS(status) # 종료 코드에 따라 return if exitCode is 24: return ENUMResources.const.TIME_OVER, res[0], usingMem elif exitCode is not 5 and exitCode is not 0 and exitCode is not 17: return ENUMResources.const.RUNTIME_ERROR, 0, 0 elif os.WIFSIGNALED(status): try: ptrace.kill(pid) except Exception as e: pass return ENUMResources.const.RUNTIME_ERROR, 0, 0 # 메모리 사용량 측정 else: usingMem = self.getUsingMemory(pid, usingMem, res[6]) ptrace.syscall(pid, 0)
def opam(args, capture=False, silent=False, cwd=None, **kwargs): """Run the opam process and capture its output.""" env = os.environ.copy() env['OPAMROOT'] = OPAMROOT if capture: proc = subprocess.Popen(['opam'] + list(args), stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env) stdout, stderr = proc.communicate() if proc.returncode != 0: print('"opam {}" failed:\n'.format(' '.join(args))) print(stderr.decode('utf-8')) sys.exit(1) return stdout.decode('utf-8') else: proc = subprocess.Popen(['opam'] + list(args), stdout=subprocess.DEVNULL if silent else None, stderr=subprocess.DEVNULL if silent else None, env=env, cwd=cwd) child_pid, status, rusage = os.wait4(proc.pid, 0) if status != 0: print('"opam {}" failed:\n'.format(' '.join(args))) sys.exit(proc.returncode) return rusage.ru_utime
def _verify(self, data, require_signature): with _Pipe() as stdin: with _Pipe() as contents: with _Pipe() as status: with _Pipe() as stderr: pid = os.fork() if pid == 0: self._exec_gpg(stdin.r, contents.w, stderr.w, status.w) else: stdin.close_r() contents.close_w() stderr.close_w() status.close_w() read = self._do_io([contents.r, stderr.r, status.r], {stdin.w: data}) stdin.w = None # was closed by _do_io (pid_, exit_code, usage_) = os.wait4(pid, 0) self.contents = read[contents.r] self.status = read[status.r] self.stderr = read[stderr.r] if self.status == "": raise GpgException("No status output from GPG. (GPG exited with status code %s)\n%s" % (exit_code, self.stderr)) for line in self.status.splitlines(): self._parse_status(line) if self.invalid: self.valid = False if require_signature and not self.valid: raise GpgException("No valid signature found. (GPG exited with status code %s)\n%s" % (exit_code, self.stderr))
def bounds_test(): try: os.mkdir('tmp') except: pass test_home = Path('tmp') break_into_separate_progs('tests_bounds.g', test_home) error_count = 0 for folderName, subfolder, filenames in os.walk(test_home): for filename in filenames: msg = subprocess.run(['./gc', (test_home / filename), '-o', (test_home / filename.strip('.g'))], capture_output=True) if (msg.returncode != 0): print(F'Error: compilation of {test_home}/{filename} failed unexpectedly:') test_file = open(test_home / filename) print(test_file.read()) error_count += 1 p = subprocess.Popen(['./'+str(test_home / filename.strip('.g'))], stderr=subprocess.DEVNULL) pid, exit_status, res_usage = os.wait4(p.pid, 0) if (exit_status == 0): error_count += 1 print(F'Error: {test_home}/{filename} executed successfully:') test_file = open(test_home / filename.strip()) print(test_file.read()) shutil.rmtree(test_home) return error_count
def Exec(argv,limit=None,pipe=None,RootDir=None): ret=[False,None,None,None] pid=os.fork() if pid==-1: return None if pid: #父进程 state=os.wait4(pid,os.WUNTRACED) # 0 ru_utime time in user mode (float) # 6 ru_minflt page faults not requiring I/O ret[2:2]=[state[2][0],state[2][6]*resource.getpagesize()] if not os.WIFEXITED(state[1]): #运行时错误 ret[1]=u"运行时错误" if (os.WIFSIGNALED(RunRet[1])) and Signal.has_key(os.WTERMSIG(RunRet[1])): ret[1]=Signal[os.WTERMSIG(RunRet[1])] else: ret[0]=True return ret else: #子进程 #未在Cygwin中实现 if limit is not None: resource.setrlimit(resource.RLIMIT_CPU,(limit[0],limit[0])) resource.setrlimit(resource.RLIMIT_AS,(limit[1]*1204*1024,limit[1]*1204*1024)) if RootDir is not None: os.chdir(RootDir) if pipe is not None and len(pipe): for i in range(0,len(pipe)): if pipe[i] is not None: os.dup2(pipe[i],i) #print "EXEC",argv os.execvp(argv[0],argv) exit(1)
def seahorn(in_name, out_name, opts, cex=None, cpu=-1, mem=-1): def set_limits(): if mem > 0: mem_bytes = mem * 1024 * 1024 resource.setrlimit(resource.RLIMIT_AS, [mem_bytes, mem_bytes]) seahorn_cmd = [ getSeahorn(), in_name, '-horn-inter-proc', '-horn-sem-lvl=mem', '-horn-step=large', '-o', out_name ] seahorn_cmd.extend(opts) if cex is not None: seahorn_cmd.append('--horn-svcomp-cex={}'.format(cex)) if verbose: print ' '.join(seahorn_cmd) p = sub.Popen(seahorn_cmd, preexec_fn=set_limits) global running_process running_process = p timer = threading.Timer(cpu, kill, [p]) if cpu > 0: timer.start() try: (pid, returnvalue, ru_child) = os.wait4(p.pid, 0) running_process = None finally: ## kill the timer if the process has terminated already if timer.isAlive(): timer.cancel() ## if seahorn did not terminate properly, propagate this error code if returnvalue != 0: sys.exit(returnvalue)
def seahorn (in_name, out_name, opts, cex = None, cpu = -1, mem = -1): def set_limits (): if mem > 0: mem_bytes = mem * 1024 * 1024 resource.setrlimit (resource.RLIMIT_AS, [mem_bytes, mem_bytes]) seahorn_cmd = [ getSeahorn(), in_name, '-horn-inter-proc', '-horn-sem-lvl=mem', '-horn-step=large', '-o', out_name] seahorn_cmd.extend (opts) if cex is not None: seahorn_cmd.append ('--horn-svcomp-cex={}'.format (cex)) if verbose: print ' '.join (seahorn_cmd) p = sub.Popen (seahorn_cmd, preexec_fn=set_limits) global running_process running_process = p timer = threading.Timer (cpu, kill, [p]) if cpu > 0: timer.start () try: (pid, returnvalue, ru_child) = os.wait4 (p.pid, 0) running_process = None finally: ## kill the timer if the process has terminated already if timer.isAlive (): timer.cancel () ## if seahorn did not terminate properly, propagate this error code if returnvalue != 0: sys.exit (returnvalue)
def record_child_pid( pid: int, record_paths: "RecordPaths", timeout: Optional[int] = None ) -> Recording: if timeout is None: options = 0 else: options = os.WNOHANG record = RecordProcess(pid, record_paths) wall_time: Optional[float] = None with record: ptrace_detach(pid) start = time.time() while True: pid, exit_code, rusage = os.wait4(pid, options) if pid != 0: if timeout is None: wall_time = time.time() - start break elif timeout is not None and time.time() - start <= 0: raise TimeoutExpired( "process did not finish within {} seconds".format(timeout) ) time.sleep(0.10) coredump, trace = record.result() return Recording(coredump, trace, exit_code, rusage, wall_time)
def __run_wait(argv, infile, outfile, errfile, timelim, memlim): logging.debug('run "%s < %s > %s 2> %s"', ' '.join(argv), infile, outfile, errfile) pid = os.fork() if pid == 0: # child try: if timelim is not None: limit.try_limit(resource.RLIMIT_CPU, timelim, timelim + 1) if memlim is not None: limit.try_limit(resource.RLIMIT_AS, memlim * (1024**2), resource.RLIM_INFINITY) limit.try_limit(resource.RLIMIT_STACK, resource.RLIM_INFINITY, resource.RLIM_INFINITY) Program.__setfd(0, infile, os.O_RDONLY) Program.__setfd(1, outfile, os.O_WRONLY | os.O_CREAT | os.O_TRUNC) Program.__setfd(2, errfile, os.O_WRONLY | os.O_CREAT | os.O_TRUNC) os.execvp(argv[0], argv) except Exception as exc: print "Oops. Fatal error in child process:" print exc os.kill(os.getpid(), signal.SIGTERM) # Unreachable logging.error("Unreachable part of run_wait reached") os.kill(os.getpid(), signal.SIGTERM) (pid, status, rusage) = os.wait4(pid, 0) return status, rusage.ru_utime + rusage.ru_stime
def run_singlemaxpairs(ifname): errs = [] sc_args = ['nice', args.safecomplete, '-json', '-single', '-in', ifname] #print(' '.join(sc_args)) sc = psutil.Popen(sc_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) folddata = None try: folddata = json.loads(sc.stdout.read().decode('utf-8')) except json.decoder.JSONDecodeError as e: errs.append('{}: Failed to decode trivial safety output:'.format( ifname, e)) err = sc.stderr.read() if err != None and len(err) > 0: errs.append('Single-Max-Pairs for {} returned errors:\n{}'.format( ifname, err)) pid, status, res = os.wait4(sc.pid, 0) #print('SMP: Status: {}, user (s): {:5.1f}, sys (s): {:5.1f}, maxrss (kB): {:6d}'.format( # status, res.ru_utime, res.ru_stime, res.ru_maxrss)) if folddata == None: return (None, errs) folddata['Command'] = ' '.join(sc_args) folddata['Resources'] = { 'User': res.ru_utime, 'Sys': res.ru_stime, 'RSS': res.ru_maxrss, } return (folddata, errs)
def _run_wait(self, argv, infile="/dev/null", outfile="/dev/null", errfile="/dev/null", timelim=1000): logging.debug('run "%s < %s > %s 2> %s"', ' '.join(argv), infile, outfile, errfile) pid = os.fork() if pid == 0: # child try: resource.setrlimit(resource.RLIMIT_CPU, (timelim, timelim + 1)) self._setfd(0, infile, os.O_RDONLY) self._setfd(1, outfile, os.O_WRONLY | os.O_CREAT | os.O_TRUNC) self._setfd(2, errfile, os.O_WRONLY | os.O_CREAT | os.O_TRUNC) os.execvp(argv[0], argv) except Exception as e: print "Error" print e os.kill(os.getpid(), signal.SIGTERM) #Unreachable logging.error("Unreachable part of run_wait reached") os.kill(os.getpid(), signal.SIGTERM) (pid, status, rusage) = os.wait4(pid, 0) return status, rusage.ru_utime + rusage.ru_stime
def exec_child(self, executable, environ=None, stdin=None, stdout=None, stderr=None, cwd=None): '''Execute a child process with the environment set from the current environment, the values of self.addtl_child_environ, the random numbers returned by self.random_val_env_vars, and the given ``environ`` (applied in that order). stdin/stdout/stderr are optionally redirected. This function waits on the child process to finish, then returns (rc, rusage), where rc is the child's return code and rusage is the resource usage tuple from os.wait4()''' all_environ = dict(os.environ) all_environ.update(self.addtl_child_environ) all_environ.update(self.random_val_env_vars()) all_environ.update(environ or {}) stdin = file(stdin, 'rb') if stdin else sys.stdin stdout = file(stdout, 'wb') if stdout else sys.stdout if stderr == 'stdout': stderr = stdout else: stderr = file(stderr, 'wb') if stderr else sys.stderr # close_fds is critical for preventing out-of-file errors proc = subprocess.Popen([executable], cwd = cwd, stdin=stdin, stdout=stdout, stderr=stderr if stderr != stdout else subprocess.STDOUT, close_fds=True, env=all_environ) # Wait on child and get resource usage (_pid, _status, rusage) = os.wait4(proc.pid, 0) # Do a subprocess.Popen.wait() to let the Popen instance (and subprocess module) know that # we are done with the process, and to get a more friendly return code rc = proc.wait() return (rc, rusage)
def watchRunProgram(self, pid): usingMem = 0 while True: wpid, status, res = os.wait4(pid, 0) signal.signal(signal.SIGXCPU, self.sigHandler) # 정상 종료된 경우 if os.WIFEXITED(status): return 'Grading', res[0], usingMem exitCode = os.WEXITSTATUS(status) # 종료 코드에 따라 return if exitCode is 24: return ENUMResources.const.TIME_OVER, res[0], usingMem elif exitCode is not 5 and exitCode is not 0 and exitCode is not 17: return ENUMResources.const.RUNTIME_ERROR, 0, 0 elif os.WIFSIGNALED(status): try: ptrace.kill(pid) except Exception as e: pass return ENUMResources.const.RUNTIME_ERROR, 0, 0 # 메모리 사용량 측정 else: usingMem = self.getUsingMemory(pid, usingMem, res[6]) ptrace.syscall(pid, 0)
def runCommand(exepath, arguments, captureStdOut): env = os.environ stdout = None if captureStdOut: (fileno, tmpfilename) = tempfile.mkstemp() stdout = os.fdopen(fileno, 'w') args = 'ulimit -v 1000000 -t 60 -c 0;' + exepath for s in arguments: args += ' "' + s + '"' process = subprocess.Popen(['/bin/bash', '-c', args], env=env, close_fds=True, stdout=stdout, stderr=None) s = os.wait4(process.pid, os.WNOHANG) waited = 0 waitstep = 0.1 maxwaittime = 65 while s[0] == 0 and s[1] == 0 and waited < maxwaittime: # wait a bit time.sleep(waitstep) waited += waitstep s = os.wait4(process.pid, os.WNOHANG) if waited >= maxwaittime: # if the process did not end nicely, kill it try: os.killpg(process.pid, signal.SIGKILL) except: pass try: s = os.wait4(process.pid, 0) except: pass r = object() r.utime = s[2].ru_utime r.stime = s[2].ru_stime r.returnValue = s[1] r.stdout = [] if captureStdOut: stdout.close() stdout = open(tmpfilename, 'r') r.stdout = stdout.readlines() stdout.close() os.remove(tmpfilename) return r
def collect_dead_children(self): dead_children = set() for pid, proc in self._processes.items(): rpid, status, resinfo = os.wait4(pid, os.WNOHANG) if rpid == 0: continue assert rpid == pid if proc.state != ProcessState.RUNNING: proc.logger.error("Unexpected state %s", proc.state) continue if os.WIFEXITED(status): proc.returncode = os.WEXITSTATUS(status) proc.logger.info("Terminated with rc=%d", proc.returncode) elif os.WIFSIGNALED(status): proc.returncode = 1 proc.signal = os.WTERMSIG(status) proc.logger.info("Terminated by signal=%d", proc.signal) elif os.WIFSTOPPED(status): sig = os.WSTOPSIG(status) proc.logger.info("Stopped by signal=%d", sig) continue else: proc.logger.error("Unexpected status %d", status) continue # The handle should receive an EOF when the child died and the # pipe gets closed. We should wait for it asynchronously. proc.stdout_protocol.eof_received() proc.stderr_protocol.eof_received() proc.resinfo = resinfo # proc.logger.info("Resource usage:") # proc.logger.info(" utime=%f", resinfo.ru_utime) # proc.logger.info(" stime=%f", resinfo.ru_stime) # proc.logger.info(" maxrss=%d", resinfo.ru_maxrss) # proc.logger.info(" ixrss=%d", resinfo.ru_ixrss) # proc.logger.info(" idrss=%d", resinfo.ru_idrss) # proc.logger.info(" isrss=%d", resinfo.ru_isrss) # proc.logger.info(" minflt=%d", resinfo.ru_minflt) # proc.logger.info(" majflt=%d", resinfo.ru_majflt) # proc.logger.info(" nswap=%d", resinfo.ru_nswap) # proc.logger.info(" inblock=%d", resinfo.ru_inblock) # proc.logger.info(" oublock=%d", resinfo.ru_oublock) # proc.logger.info(" msgsnd=%d", resinfo.ru_msgsnd) # proc.logger.info(" msgrcv=%d", resinfo.ru_msgrcv) # proc.logger.info(" nsignals=%d", resinfo.ru_nsignals) # proc.logger.info(" nvcsw=%d", resinfo.ru_nvcsw) # proc.logger.info(" nivcsw=%d", resinfo.ru_nivcsw) proc.state = ProcessState.FINISHED proc.term_event.set() dead_children.add(pid) for pid in dead_children: self._child_collector.remove_child(pid) del self._processes[pid]
def _try_wait(self, wait_flags): try: (pid, sts, res) = os.wait4(self.pid, wait_flags) self._resources = res except ChildProcessError: pid = self.pid sts = 0 return (pid, sts)
def __wait4(self, mu, pid, wstatus, options, ru): assert ru == 0 #return pid logger.warning("syscall wait4 pid %d" % pid) t = os.wait4(pid, options) logger.info("wait4 return %r" % (t, )) mu.mem_write(wstatus, int(t[1]).to_bytes(4, "little")) return t[0]
def timeExec(cmd, cwd=None, env=None): from subprocess import Popen, STDOUT DEVNULL = open(os.devnull, 'wb', 0) proc = subprocess.Popen(cmd, stdout=DEVNULL, stderr=DEVNULL, cwd=cwd, env=envFor(env)) _,result,resources = os.wait4(proc.pid, 0) return bool(result), resources.ru_utime + resources.ru_stime
def run_test_cpp(name, args): p = subprocess.Popen(([str(name) + '_cpp'] + args)) pid, exit_status, res_usage = os.wait4(p.pid, 0) result = res_usage.ru_utime + res_usage.ru_stime print( f"C++ Execution time: {(1000 * result):.0f} ms (user = {1000 * res_usage.ru_utime:.0f} ms, " + f"sys = {1000 * res_usage.ru_stime:.0f} ms)") return result
def _wait_for(pid): # Keep retrying os.wait4 until it does not get interrupted. while True: try: return os.wait4(pid, 0) except OSError as e: if e.errno != errno.EINTR: raise
def __wait4(self, mu, pid, wstatus, options, ru): assert ru == 0 #return pid logging.debug("syscall wait4 pid %d" % pid) t = os.wait4(pid, options) logging.debug("wait4 return %r" % (t, )) #wstatus 只是一个int指针,固定是4 mu.mem_write(wstatus, int(t[1]).to_bytes(4, "little")) return t[0]
def reap(self, pid=None, wait=False): if pid is None: pid = self.reap_pid waittime = time.time() pid, status, rusage = os.wait4(pid, 0 if wait else os.WNOHANG) log.debug('wait4 => ' + repr((pid, status, rusage))) if pid != 0: reaped[pid] = obit = obituary(waittime, pid, status, rusage) self.dispatch(obit) return pid
def run(self, args=list(), stdin=None, stdout=None, stderr=None, max_time=1, max_memory=256, max_output_size=256): os.chdir(self.workspace) child_pid = os.fork() max_memory = max_memory * 1024 * 1204 max_output_size = max_output_size * 1024 * 1024 max_real_time = max_time * 2 stdin, stdout, stderr = self.try_to_open_file((stdin, "r"), (stdout, "w"), (stderr, "w")) if child_pid == 0: # in the child now try: os.setpgrp() self.set_resource_limit(max_time=max_time, max_memory=max_memory, max_output_size=max_output_size) os.dup2(stdin.fileno(), 0) os.dup2(stdout.fileno(), 1) os.dup2(stderr.fileno(), 2) os.execve(self.config["execute_file"], [self.config["execute_file"]] + self.config.get("execute_args", []) + args, {}) except: traceback.print_exc() os._exit(-777) # Magic number, indicates something wrong during execution else: killer = threading.Timer(max_real_time, os.killpg, (child_pid, signal.SIGKILL)) killer.start() start_time = time.time() pid, status, rusage = os.wait4(child_pid, os.WSTOPPED) stop_time = time.time() real_time_consumed = stop_time - start_time if killer: killer.cancel() result = {"time": rusage.ru_utime, "memory": round(rusage.ru_maxrss / 1024), "exit_code": os.WEXITSTATUS(status), "signal": os.WTERMSIG(status) if os.WIFSIGNALED(status) else 0, "verdict": "OK"} if result["exit_code"] != 0: result["verdict"] = "RUNTIME_ERROR" if result["exit_code"] == -777: # Magic number, see above result["verdict"] = "SYSTEM_ERROR" elif self.platform not in ("darwin", ) and result["memory"] * 1048576 > max_memory: result["verdict"] = "MEMORY_LIMIT" elif result["time"] > max_time: result["verdict"] = "TIME_LIMIT" elif real_time_consumed > max_real_time: result["verdict"] = "IDLENESS_LIMIT" elif result["signal"] != 0: if result["signal"] == signal.SIGUSR1: result["verdict"] = "SYSTEM_ERROR" else: result["verdict"] = "RUNTIME_ERROR" stdin.close() stdout.close() stderr.close() return result
def run_test_cs_mono_aot(name, args): args = ['mono', '--aot-path=benchmark/aot', (str(name) + '_cs')] + args p = subprocess.Popen(args) pid, exit_status, res_usage = os.wait4(p.pid, 0) result = res_usage.ru_utime + res_usage.ru_stime print( f"C#(MONO AOT) Execution time: {(1000 * result):.0f} ms (user = {1000 * res_usage.ru_utime:.0f} ms, " + f"sys = {1000 * res_usage.ru_stime:.0f} ms)") return result
def crabllvm (in_name, out_name, args, extra_opts, cpu = -1, mem = -1): def set_limits (): if mem > 0: mem_bytes = mem * 1024 * 1024 resource.setrlimit (resource.RLIMIT_AS, [mem_bytes, mem_bytes]) crabllvm_cmd = [ getCrabLlvm(), in_name, '-oll', out_name] crabllvm_cmd = crabllvm_cmd + extra_opts if args.log is not None: for l in args.log.split (':'): crabllvm_cmd.extend (['-log', l]) if args.undef_nondet: crabllvm_cmd.append( '--crab-turn-undef-nondet') if args.lower_select: crabllvm_cmd.append( '--crab-lower-select') crabllvm_cmd.append ('--crab-dom={0}'.format (args.crab_dom)) crabllvm_cmd.append ('--crab-inter-sum-dom={0}'.format (args.crab_inter_sum_dom)) crabllvm_cmd.append ('--crab-widening-delay={0}'.format (args.widening_delay)) crabllvm_cmd.append ('--crab-widening-jump-set={0}'.format (args.widening_jump_set)) crabllvm_cmd.append ('--crab-narrowing-iterations={0}'.format (args.narrowing_iterations)) if (args.crab_dom == 'adapt-rtz'): crabllvm_cmd.append ('--crab-adapt-rtz-threshold={0}'.format (args.num_threshold)) crabllvm_cmd.append ('--crab-track={0}'.format (args.track)) if args.crab_disable_offsets: crabllvm_cmd.append ('--crab-disable-offsets') if args.crab_singleton_aliases: crabllvm_cmd.append ('--crab-singleton-aliases') if args.crab_inter: crabllvm_cmd.append ('--crab-inter') if args.crab_live: crabllvm_cmd.append ('--crab-live') crabllvm_cmd.append ('--crab-add-invariants={0}'.format (args.insert_invs)) crabllvm_cmd.append ('--crab-print-invariants') if args.show_summs: crabllvm_cmd.append ('--crab-print-summaries') if args.print_cfg: crabllvm_cmd.append ('--crab-print-cfg') if args.print_stats: crabllvm_cmd.append ('--crab-stats') # hidden options if args.crab_cfg_simplify: crabllvm_cmd.append ('--crab-cfg-simplify') if args.crab_keep_shadows: crabllvm_cmd.append ('--crab-keep-shadows') if verbose: print ' '.join (crabllvm_cmd) if args.out_name is not None: crabllvm_cmd.append ('-o={0}'.format (args.out_name)) p = sub.Popen (crabllvm_cmd, preexec_fn=set_limits) global running_process running_process = p timer = threading.Timer (cpu, kill, [p]) if cpu > 0: timer.start () try: (pid, returnvalue, ru_child) = os.wait4 (p.pid, 0) running_process = None finally: ## kill the timer if the process has terminated already if timer.isAlive (): timer.cancel () ## if crabllvm did not terminate properly, propagate this error code if returnvalue != 0: sys.exit (returnvalue)
def reproject_to_webmercator(params, context): # TO-DO: Catch an exception if there isn't a .tif output file srcpath = os.path.join(params['env']['outputdir'], 'demoSDM') # Fetch the current and future projection files srcfiles = [x for x in glob.iglob(os.path.join(srcpath, 'proj_*', 'proj_*.tif')) if 'Clamping' not in x] if len(srcfiles) < 2: raise Exception("Projection failed: expected current and future projection, but {} found".format(len(srcfiles))) # Create a color file coltxt = ['1000 216 7 7 255', '900 232 16 16 255', '800 234 39 39 255', '700 236 66 66 255', '600 239 96 96 255', '500 242 128 128 255', '400 246 159 159 255', '300 249 189 189 255', '200 251 216 216 255', '100 253 239 239 255', '0% 255 255 255 255', 'nv 255 255 255 0'] colsrc = os.path.join(params['env']['outputdir'], 'col.txt') with open(colsrc, 'w') as f: for color in coltxt: f.write('%s\n' % color) scriptout = os.path.join(params['env']['outputdir'], params['worker']['script']['name'] + 'out') outfile = open(scriptout, 'w') # Reproject using Web Mercator projection, and save as png file destfiles = [] for srcfile in srcfiles: wmcfile = os.path.join(srcpath, 'webmcproj.tif') destfile = os.path.splitext(srcfile)[0] + '.png' destfiles.append(destfile) commreproj = ['/usr/bin/gdalwarp', '-s_srs', 'epsg:4326', '-t_srs', 'epsg:3857', srcfile, wmcfile] commrelief = ['/usr/bin/gdaldem', 'color-relief', '-of', 'PNG', wmcfile, colsrc, destfile, '-alpha'] try: proc = subprocess.Popen(commreproj, close_fds=True, stdout=outfile, stderr=subprocess.STDOUT) rpid, ret, rusage = os.wait4(proc.pid, 0) proc = subprocess.Popen(commrelief, close_fds=True, stdout=outfile, stderr=subprocess.STDOUT) rpid, ret, rusage = os.wait4(proc.pid, 0) except Exception as e: raise return destfiles
def run(self): proc = subprocess.Popen(self.prog, stderr=subprocess.DEVNULL, preexec_fn=self.preexec, cwd=self.cwd) tused = 0 mused = 0 while True: _, status, rusage = os.wait4(proc.pid, 0) tused = rusage.ru_utime if os.WIFEXITED(status) or os.WIFSIGNALED(status): if os.WIFEXITED(status) and not os.WEXITSTATUS(status): result = JudgeResult.NORMAL else: result = JudgeResult.RUNTIME_ERROR break # WIFSTOPPED if os.WSTOPSIG(status) == signal.SIGXCPU: proc.kill() result = JudgeResult.TIME_LIMIT_EXCEEDED break if os.WSTOPSIG(status) not in (signal.SIGTRAP, signal.SIGWINCH): proc.kill() result = JudgeResult.RUNTIME_ERROR break # Check time usage if tused > self.limits.time_limit: proc.kill() result = JudgeResult.TIME_LIMIT_EXCEEDED break # Check memory usage with open('/proc/{}/status'.format(proc.pid), 'r') as fp: for line in fp: if line.startswith('VmPeak:'): mused = int(line[7:-3]) * 1024 if mused > self.limits.memory_limit: proc.kill() result = JudgeResult.MEMORY_LIMIT_EXCEEDED break try: ptrace.syscall(proc.pid, 0) except ProcessLookupError: # Child process dies pass resource_usage = ResourceUsage(time_usage=tused, memory_usage=mused) return result, resource_usage
def search(keyword=None, location=None): try: for module_name in MODULES.keys(): MODULES[module_name] = os.fork() if MODULES[module_name] == 0: try: #models.Platform.objects.get_or_create(name=module_name) log.notice('Search on %s' % module_name) module = __import__(module_name) func = getattr(module, 'main') func(keyword=keyword, location=location) except (SystemExit, KeyboardInterrupt): log.notice('Abording search %s' % module_name) except Exception as e: log.error('%s' % e) try: traceback.print_exc() # Print an informative traceback except: pass sys.exit(0) def receive_signal(signum, stack): for module_name,pid in MODULES.items(): log.debug('Abording search %s' % module_name) os.kill(pid, signal.SIGTERM) #del MODULES[module_name] sys.exit(0) signal.signal(signal.SIGTERM, receive_signal) for module_name,pid in MODULES.items(): try: os.wait4(pid, 0) #del MODULES[module_name] except (SystemExit, KeyboardInterrupt): log.notice('Stop search') sys.exit(0) except Exception as e: log.error('%s' % e) try: traceback.print_exc() # Print an informative traceback except: pass
def wait_impl(self, cpid): for i in range(10): # wait4() shouldn't hang, but some of the buildbots seem to hang # in the forking tests. This is an attempt to fix the problem. spid, status, rusage = os.wait4(cpid, os.WNOHANG) if spid == cpid: break time.sleep(1.0) self.assertEqual(spid, cpid) self.assertEqual(status, 0, "cause = %d, exit = %d" % (status&0xff, status>>8)) self.assertTrue(rusage)
def GetExitInfo (self): xc = None treal = time.time() - self.launchTime tuser = treal tsys = 0.0 rss = 0 if hasattr(os, 'wait4'): # use wait4 if available so we can get usr/sys times & rss v = os.wait4(self.pid, os.WNOHANG) if 0 == v[0]: xc = None # still running else: xc = v[1] # exit code if os.WIFEXITED(xc): xc = os.WEXITSTATUS(xc) elif os.WIFSIGNALED(xc): xc = -os.WTERMSIG(xc) v = v[2] # resource.struct_rusage tuser = v.ru_utime tsys = v.ru_stime rss = v.ru_maxrss if sys.platform == 'darwin': # despite the getrusage manpage claims, on OSX we get # rss *bytes* here, rather than kbytes. Unclear if that # is a manpage bug, python bug, wait4 bug, or kernel bug. rss /= 1024 else: xc = self.poll() # fall back to subprocess module if xc is None: return (None, None, []) # process running, STILL_ACTIVE rusage = [treal, tuser, tsys, rss] if xc == 0: return (0, "done", rusage) elif subprocess.mswindows: # check for windows exception codes (WinNT.h) xc = long(xc) if xc < 0: # grr, python (2.6 and prior) treats DWORD as signed int32? xc = long(2**32) + xc # two's compliment of 32-bit value if (0xC0000000L & xc): s = "exit with exception - " if 0xC000013AL == xc: # STATUS_CONTROL_C_EXIT s += "Ctrl-C" elif 0xC0000005L == xc: # STATUS_ACCESS_VIOLATION s += "Access Violation"
def wait_for_child_and_forward_all_signals(child_pid, process_name): """Wait for a child to terminate and in the meantime forward all signals the current process receives to this child. @return a tuple of exit code and resource usage of the child as given by os.waitpid """ assert _HAS_SIGWAIT block_all_signals() while True: logging.debug("Waiting for signals") signum = signal.sigwait(_ALL_SIGNALS) if signum == signal.SIGCHLD: pid, exitcode, ru_child = os.wait4(-1, os.WNOHANG) while pid != 0: if pid == child_pid: return exitcode, ru_child else: logging.debug("Received unexpected SIGCHLD for PID %s", pid) pid, exitcode, ru_child = os.wait4(-1, os.WNOHANG) else: _forward_signal(signum, child_pid, process_name)
def wait_deadline(pid, options, deadline, interval=0.05): while True: (child_pid, child_exit, child_resource) = os.wait4(pid, options) child_signal = child_exit % 256 if child_signal > 0: child_exit = 128 + child_signal else: child_exit = child_exit >> 8 if child_pid != 0: return (child_pid, child_exit, child_resource) if time.time() >= deadline: return (child_pid, child_exit, child_resource) time.sleep(interval)
def poll(self): if self.obituary is not None: return self.obituary waittime = time.time() pid, status, rusage = os.wait4(self.pid, os.WNOHANG) self.log.debug('poll wait wanted {0} got {1}'.format(self.pid, pid)) if pid == self.pid: obit = obituary(waittime, pid, status, rusage) handle = reaper.theReaper.dispatch if reaper.theReaper \ else self.handle_obituary self.log.debug('dispatch to ' + repr(handle)) handle(obit) return obit assert pid == 0
def run(cmd, in_path, out_path, *args): pid = os.fork() if pid == 0: if in_path: with open(in_path, 'r') as in_file: os.dup2(in_file.fileno(), 0) with open(out_path, 'w') as out_file: os.dup2(out_file.fileno(), 1) with open('/dev/null', 'w') as err_file: os.dup2(err_file.fileno(), 2) os.execl(cmd, cmd, *args) (pid, status, rusage) = os.wait4(pid, 0) status = os.WEXITSTATUS(status) == 0 wtime = rusage.ru_utime + rusage.ru_stime return status, wtime
def _wait_for_process(self, pid, name): """Wait for the given process to terminate. @return tuple of exit code and resource usage """ try: logging.debug("Waiting for process %s with pid %s", name, pid) unused_pid, exitcode, ru_child = os.wait4(pid, 0) return exitcode, ru_child except OSError as e: if self.PROCESS_KILLED and e.errno == errno.EINTR: # Interrupted system call seems always to happen # if we killed the process ourselves after Ctrl+C was pressed # We can try again to get exitcode and resource usage. logging.debug("OSError %s while waiting for termination of %s (%s): %s.", e.errno, name, pid, e.strerror) try: unused_pid, exitcode, ru_child = os.wait4(pid, 0) return exitcode, ru_child except OSError: pass # original error will be handled and this ignored logging.critical("OSError %s while waiting for termination of %s (%s): %s.", e.errno, name, pid, e.strerror) return (0, None)
def run_wait(cmd, args, infile="/dev/null", outfile="/dev/null", errfile="/dev/null"): # logging.debug('run_wait(%s, %s, infile=%s, outfile=%s, errfile=%s)', cmd, args, infile, outfile, errfile) pid = os.fork() if pid == 0: # child try: _setfd(0, infile, os.O_RDONLY) _setfd(1, outfile, os.O_WRONLY | os.O_CREAT | os.O_TRUNC) _setfd(2, errfile, os.O_WRONLY | os.O_CREAT | os.O_TRUNC) os.execvp(cmd, args) except: os.kill(os.getpid(), signal.SIGTERM) #Unreachable os.kill(os.getpid(), signal.SIGTERM) else: (pid, status, rusage) = os.wait4(pid, 0) return status, rusage.ru_utime + rusage.ru_stime
def run_and_time(name, args): """Run the given arguments, print the times.""" start = time.time() child = run_child(name, args) _, status, rusage = os.wait4(child.pid, 0) end = time.time() if verbose == 2: print 'Ran %s -> %d' % (args, status) if status != 0: print 'Error running %s: %s' % (args[0], status) raise RuntimeError print '%-10s u:%.3f s:%.3f r:%.3f' % ( name, rusage.ru_utime, rusage.ru_stime, end - start)
def wait_impl(self, cpid): option = os.WNOHANG if sys.platform.startswith('aix'): # Issue #11185: wait4 is broken on AIX and will always return 0 # with WNOHANG. option = 0 for i in range(10): # wait4() shouldn't hang, but some of the buildbots seem to hang # in the forking tests. This is an attempt to fix the problem. spid, status, rusage = os.wait4(cpid, option) if spid == cpid: break time.sleep(1.0) self.assertEqual(spid, cpid) self.assertEqual(status, 0, "cause = %d, exit = %d" % (status&0xff, status>>8)) self.assertTrue(rusage)