def test_setsid_helper(self): got = [] def callback(pid, status): got.append((pid, status)) spec1 = {"args": ["sh", "-c", "exit 42"], "fds": {0: sys.stdin, 1: sys.stdout, 2: sys.stderr}} spec2 = {"args": ["sh", "-c", "exit 24"], "fds": {0: sys.stdin, 1: sys.stdout, 2: sys.stderr}} master_fd, slave_fd = terminal.openpty() helper_pid, pids = setsid_helper.run([spec1, spec2], slave_fd, callback) self.assertEquals(len(pids), 2) gobject.main_context_default().iteration(True) gobject.main_context_default().iteration(True) gobject.main_context_default().iteration(True) statuses = dict(got) self.assertEquals(set(statuses.keys()), set(pids)) assert os.WIFEXITED(statuses[pids[0]]) assert os.WIFEXITED(statuses[pids[1]]) self.assertEquals(os.WEXITSTATUS(statuses[pids[0]]), 42) self.assertEquals(os.WEXITSTATUS(statuses[pids[1]]), 24) # Helper process should exit OK. pid2, status = os.waitpid(helper_pid, 0) assert os.WIFEXITED(status) self.assertEquals(os.WEXITSTATUS(status), 0)
def start_job(self, job_procs, is_foreground, cmd_text): dispatcher_for_job = SessionHelperDispatcher() helper_pid, pids = setsid_helper.run( job_procs, self._tty_fd, dispatcher_for_job.handle_status) # Wait for helper process so that it doesn't become a zombie. self._dispatcher.add_handler(helper_pid, lambda status: None) # We must ensure that FDs are dropped before any waiting. job_procs[:] = [] procs = [ChildProcess(dispatcher_for_job, proc) for proc in pids] pgid = pids[0] job = Job(procs, pgid, cmd_text, self._to_foreground) self._job_controller.add_job(job, is_foreground)