def exit(self, code=None, timeout=5):
        """
        Wait for process to exit or until timeout (5 sec by default) and asserts
        that process exits with ``code``. If ``code`` is ``None``, returns the code
        the process exited with.

        ..note:: In order to ensure that spawned child processes do not outlive the check that spawned them, it is good practice to call either method (with no arguments if the exit code doesn't matter) or ``.kill()`` on every spawned process.

        :param code: code to assert process exits with
        :type code: int
        :param timeout: maximum number of seconds to wait for the program to end
        :type timeout: int / float
        :raises check50.Failure: if ``code`` is given and does not match the actual exitcode within ``timeout``

        Example usage::

            check50.run("./hello").exit(0)

            code = check50.run("./hello").exit()
            if code != 0:
                raise check50.Failure(f"expected exit code 0, not {code}")


        """
        self._wait(timeout)

        if code is None:
            return self.exitcode

        log(_("checking that program exited with status {}...").format(code))
        if self.exitcode != code:
            raise Failure(_("expected exit code {}, not {}").format(code, self.exitcode))
        return self