diff options
-rwxr-xr-x | tcvt.py | 39 |
1 files changed, 33 insertions, 6 deletions
@@ -732,32 +732,58 @@ class ForkPty(object): self.environ = environ self.pid = -1 self.masterfd = -1 + self.startpipew = -1 + self.errpiper = -1 self.exitcode = 255 def __enter__(self): assert self.pid == -1 assert self.masterfd == -1 - errpiper, errpipew = os.pipe() + assert self.startpipew == -1 + assert self.errpiper == -1 + startpiper, self.startpipew = os.pipe() + self.errpiper, errpipew = os.pipe() set_cloexec(errpipew) self.pid, self.masterfd = pty.fork() if self.pid == 0: # child - os.close(errpiper) + os.close(self.startpipew) + os.close(self.errpiper) os.environ.update(self.environ) + # wait for the parent + os.read(startpiper, 1) + os.close(startpiper) try: os.execvp(self.argv[0], self.argv) except OSError as err: os.write(errpipew, "exec failed: %s" % (err,)) sys.exit(255) + os.close(startpiper) os.close(errpipew) - data = os.read(errpiper, 1024) - os.close(errpiper) + return self.masterfd + + def start(self): + """Allow the process to start executing. + @raises ExecutionError: when execvp in the child fails + """ + assert self.startpipew >= 0 + assert self.errpiper >= 0 + # signal that execvp can proceed + os.write(self.startpipew, b"\0") + os.close(self.startpipew) + self.startpipew = -1 + # check for execvp errors + data = os.read(self.errpiper, 1024) + os.close(self.errpiper) + self.errpiper = -1 if data: raise ExecutionError(data) - return self.masterfd - def __exit__(self, *_): + assert self.pid > 0 + assert self.masterfd >= 0 + assert self.startpipew == -1 + assert self.errpiper == -1 os.close(self.masterfd) status = os.waitpid(self.pid, 0)[1] if status & 0xff == 0: # not killed by a signal @@ -779,6 +805,7 @@ def main(): with process as masterfd: with Terminal(acsc, options.columns, reverse=options.reverse) as t: t.resizepty(masterfd) + process.start() while True: timeout = 0 if t.refresh_needed() else None try: |