blob: ab256a8a46bd4d6a36a50cb2513e20b4a1200245 [file] [log] [blame]
# Copyright 2014 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Process related utilities."""
from __future__ import print_function
import errno
import os
import signal
import sys
import time
def GetExitStatus(status):
"""Get the exit status of a child from an os.waitpid call.
Args:
status: The return value of os.waitpid(pid, 0)[1]
Returns:
The exit status of the process. If the process exited with a signal,
the return value will be 128 plus the signal number.
"""
if os.WIFSIGNALED(status):
return 128 + os.WTERMSIG(status)
else:
assert os.WIFEXITED(status), 'Unexpected exit status %r' % status
return os.WEXITSTATUS(status)
def ExitAsStatus(status):
"""Exit the same way as |status|.
If the status field says it was killed by a signal, then we'll do that to
ourselves. Otherwise we'll exit with the exit code.
See http://www.cons.org/cracauer/sigint.html for more details.
Args:
status: A status as returned by os.wait type funcs.
"""
exit_status = os.WEXITSTATUS(status)
if os.WIFSIGNALED(status):
# Kill ourselves with the same signal.
sig_status = os.WTERMSIG(status)
pid = os.getpid()
os.kill(pid, sig_status)
time.sleep(0.1)
# Still here? Maybe the signal was masked.
try:
signal.signal(sig_status, signal.SIG_DFL)
except RuntimeError as e:
if e.args[0] != errno.EINVAL:
raise
os.kill(pid, sig_status)
time.sleep(0.1)
# Still here? Just exit.
exit_status = 127
# Exit with the code we want.
sys.exit(exit_status)