def test__raises_exception_when_child_exits_with_non_zero_code(self): exit_code = randint(1, 99) expected_message = re.escape("Child exited with code %s" % exit_code) with ExpectedException(PipeForkError, expected_message): with pipefork() as (pid, fin, fout): if pid == 0: os._exit(exit_code)
def test__raises_childs_exception_when_child_crashes(self): # If the child process exits with an exception, it is passed back to # the parent via a pickled t.p.failure.Failure, and re-raised. with ExpectedException(ZeroDivisionError): with pipefork() as (pid, fin, fout): if pid == 0: # Child. raise ZeroDivisionError()
def test__SystemExit_in_child_is_not_raised_in_parent(self): # All exceptions are pickled and passed back to the parent process, # except for SystemExit. It instead results in a call to os._exit(). exit_code = randint(1, 99) expected_message = re.escape("Child exited with code %s" % exit_code) with ExpectedException(PipeForkError, expected_message): with pipefork() as (pid, fin, fout): if pid == 0: raise SystemExit(exit_code)
def test__raises_parents_exception_when_parent_crashes(self): # If the parent raises an exception, it is propagated. During # tear-down of the pipefork's context the child is reaped, but any # exceptions (via the crash file, or raised on behalf of the child # because of a non-zero exit code or non-zero signal) propagating back # from the child are masked by the exception in the parent. with ExpectedException(ZeroDivisionError): with pipefork() as (pid, fin, fout): if pid != 0: # Parent. raise ZeroDivisionError()
def test__raises_exception_when_child_killed_by_signal(self): expected_message = re.escape("Child killed by signal 15 (SIGTERM)") with ExpectedException(PipeForkError, expected_message): with pipefork() as (pid, fin, fout): if pid == 0: # Reset SIGTERM to the default handler; the Twisted # reactor may have clobbered it in the parent. signal.signal(signal.SIGTERM, signal.SIG_DFL) # Close `fout` to signal to parent that we're running. fout.close() time.sleep(10) else: # Wait for child to close its `fout` before signalling. fin.read() os.kill(pid, signal.SIGTERM)
def test__forks(self): with pipefork() as (pid, fin, fout): if pid == 0: # Child. message_in = fin.read() message_out = b"Hello %s!" % message_in fout.write(message_out) fout.close() else: # Parent. message_out = factory.make_name("Parent").encode("ascii") fout.write(message_out) fout.close() message_in = fin.read() self.assertEqual(b"Hello %s!" % message_out, message_in)