Merge branch 'nicfit-exitcodes'

This commit is contained in:
Anthony Scopatz 2015-11-21 22:06:28 -05:00
commit 9a35c6726e
3 changed files with 51 additions and 16 deletions

View file

@ -114,20 +114,28 @@ else:
job['status'] = 'running'
os.kill(obj.pid, signal_to_send)
if job['bg']:
_give_terminal_to(_shell_pgrp)
return
_, s = os.waitpid(obj.pid, os.WUNTRACED)
if os.WIFSTOPPED(s):
_, wcode = os.waitpid(obj.pid, os.WUNTRACED)
if os.WIFSTOPPED(wcode):
job['bg'] = True
job['status'] = 'stopped'
print() # get a newline because ^Z will have been printed
print_one_job(act)
elif os.WIFSIGNALED(s):
elif os.WIFSIGNALED(wcode):
print() # get a newline because ^C will have been printed
obj.signal = (os.WTERMSIG(wcode), os.WCOREDUMP(wcode))
obj.returncode = None
else:
obj.returncode = os.WEXITSTATUS(wcode)
obj.signal = None
if obj.poll() is not None:
builtins.__xonsh_active_job__ = None
_give_terminal_to(_shell_pgrp) # give terminal back to the shell

View file

@ -390,21 +390,37 @@ class TeePTYProc(object):
@property
def returncode(self):
"""The return code of the spawned process."""
return self._tpty.returncode
"""The return value of the spawned process or None if the process
exited due to a signal."""
if os.WIFEXITED(self._tpty.wcode):
return os.WEXITSTATUS(self._tpty.wcode)
else:
return None
@property
def signal(self):
"""If the process was terminated by a signal a 2-tuple is returned
containing the signal number and a boolean indicating whether a core
file was produced. Otherwise None is returned."""
if os.WIFSIGNALED(self._tpty.wcode):
return (os.WTERMSIG(self._tpty.wcode),
os.WCOREDUMP(self._tpty.wcode))
else:
return None
def poll(self):
"""Polls the spawned process and returns the returncode."""
return self._tpty.returncode
"""Polls the spawned process and returns the os.wait code."""
return _wcode_to_popen(self._tpty.wcode)
def wait(self, timeout=None):
"""Waits for the spawned process to finish, up to a timeout."""
"""Waits for the spawned process to finish, up to a timeout.
Returns the return os.wait code."""
tpty = self._tpty
t0 = time.time()
while tpty.returncode is None:
while tpty.wcode is None:
if timeout is not None and timeout < (time.time() - t0):
raise TimeoutExpired
return tpty.returncode
return _wcode_to_popen(tpty.wcode)
@property
def stdout(self):
@ -418,3 +434,14 @@ class TeePTYProc(object):
else:
self._stdout = self._tpty.buffer
return self._stdout
def _wcode_to_popen(code):
"""Converts os.wait return code into Popen format."""
if os.WIFEXITED(code):
return os.WEXITSTATUS(code)
elif os.WIFSIGNALED(code):
return -1 * os.WTERMSIG(code)
else:
# Can this happen? Let's find out. Returning None is not an option.
raise ValueError("Invalid os.wait code: {}".format(code))

View file

@ -89,7 +89,7 @@ class TeePTY(object):
self.encoding = encoding
self.errors = errors
self.buffer = io.BytesIO()
self.returncode = None
self.wcode = None # os.wait encoded retval
self._temp_stdin = None
def __str__(self):
@ -120,8 +120,8 @@ class TeePTY(object):
Returns
-------
returncode : int
Return code for the spawned process.
wcode : int
Return code for the spawned process encoded as os.wait format.
"""
assert self.master_fd is None
self._in_alt_mode = False
@ -163,13 +163,13 @@ class TeePTY(object):
if restore:
tty.tcsetattr(pty.STDIN_FILENO, tty.TCSAFLUSH, mode)
_, self.returncode = os.waitpid(pid, 0)
_, self.wcode = os.waitpid(pid, 0)
os.close(master_fd)
self.master_fd = None
self._in_alt_mode = False
if on_main_thread:
signal.signal(signal.SIGWINCH, old_handler)
return self.returncode
return self.wcode
def _init_fd(self):
"""Called once when the pty is first set up."""
@ -329,4 +329,4 @@ if __name__ == '__main__':
print('-=-'*10)
print(tpty)
print('-=-'*10)
print('Returned with status {0}'.format(tpty.returncode))
print('Returned with status {0}'.format(tpty.wcode))