Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions core/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
from signal import (SIG_DFL, SIG_IGN, SIGINT, SIGPIPE, SIGQUIT, SIGTSTP,
SIGTTOU, SIGTTIN, SIGWINCH)

import libc

from _devbuild.gen.id_kind_asdl import Id
from _devbuild.gen.runtime_asdl import (job_state_e, job_state_t,
job_state_str, wait_status,
Expand Down Expand Up @@ -2019,6 +2021,17 @@ def NumRunning(self):
NO_ARG = -20





def GetSignalMessage(sig_num):
# type: (int) -> Optional[str]
"""Get signal message from libc."""
if mylib.PYTHON:
return libc.strsignal(sig_num)
return None


class Waiter(object):
"""A capability to wait for processes.

Expand Down Expand Up @@ -2141,6 +2154,18 @@ def WaitForOne(self, waitpid_options=0):
# Print newline after Ctrl-C.
if term_sig == SIGINT:
print('')
else:
msg = GetSignalMessage(term_sig)
if msg is not None:
if mylib.PYTHON:
# WCOREDUMP is only available on some systems
try:
from os import WCOREDUMP # type: ignore
if WCOREDUMP(status):
msg = msg + ' (core dumped)'
except (ImportError, AttributeError):
pass
print_stderr(msg)

if proc:
proc.WhenExited(pid, status)
Expand Down
29 changes: 29 additions & 0 deletions pyext/libc.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
#include <limits.h>
#include <wchar.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <locale.h>
#include <fnmatch.h>
Expand Down Expand Up @@ -379,6 +382,30 @@ func_sleep_until_error(PyObject *self, PyObject *args) {
return PyInt_FromLong(result);
}

static PyObject *
func_strsignal(PyObject *self, PyObject *args) {
int sig_num;
char *res;

if (!PyArg_ParseTuple(args, "i:strsignal", &sig_num)) {
return NULL;
}

if (sig_num < 1 || sig_num >= NSIG) {
PyErr_SetString(PyExc_ValueError, "signal number out of range");
return NULL;
}

errno = 0;
res = strsignal(sig_num);

if (errno || res == NULL || strstr(res, "Unknown signal") != NULL) {
Py_RETURN_NONE;
}

return PyString_FromString(res);
}

static PyMethodDef methods[] = {
// Return the canonical version of a path with symlinks, or None if there is
// an error.
Expand Down Expand Up @@ -416,6 +443,8 @@ static PyMethodDef methods[] = {
{"cpython_reset_locale", func_cpython_reset_locale, METH_NOARGS, ""},

{"sleep_until_error", func_sleep_until_error, METH_VARARGS, ""},

{"strsignal", func_strsignal, METH_VARARGS, ""},
{NULL, NULL},
};

Expand Down
2 changes: 2 additions & 0 deletions pyext/libc.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,5 @@ def realpath(path: str) -> str: ...
def cpython_reset_locale() -> None: ...

def sleep_until_error(seconds: float) -> int: ...

def strsignal(sig_num: int) -> Optional[str]: ...
10 changes: 10 additions & 0 deletions pyext/libc_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"""
import unittest
import sys
import signal

import libc # module under test

Expand Down Expand Up @@ -367,6 +368,15 @@ def testSleepUntilError(self):

# Not testing errno case

def testStrsignal(self):
self.assertEqual('Segmentation fault', libc.strsignal(11))
self.assertEqual('Aborted', libc.strsignal(6))
self.assertEqual('Illegal instruction', libc.strsignal(4))
self.assertEqual('Terminated', libc.strsignal(signal.SIGTERM))

with self.assertRaises(ValueError):
libc.strsignal(999)


if __name__ == '__main__':
# To simulate the OVM_MAIN patch in pythonrun.c
Expand Down
24 changes: 22 additions & 2 deletions spec/background.test.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## oils_failures_allowed: 3
## oils_failures_allowed: 8
## compare_shells: dash bash mksh

# Job control constructs:
Expand Down Expand Up @@ -54,7 +54,7 @@ wait -n
#### wait with jobspec syntax %nonexistent
wait %nonexistent
## status: 127
## OK dash status: 2
## N-I dash status: 2

#### wait with invalid PID
wait 12345678
Expand Down Expand Up @@ -162,6 +162,10 @@ echo status=$?
status=0
status=99
## END
## N-I mksh STDOUT:
status=0
status=127
## END

#### Wait for job and PIPESTATUS

Expand Down Expand Up @@ -396,3 +400,19 @@ wait --all 1

## N-I dash/bash/mksh STDOUT:
## END

#### Signal message for killed background job
case $SH in dash|mksh) exit ;; esac

sleep 1 &
kill -HUP $!
wait $! 2>err.txt
echo status=$?
grep -o "Hangup" err.txt
## status: 0
## STDOUT:
status=129
Hangup
## END
## STDERR:
## END
Loading