commit 1a1c8a87cb6e966c8d716a90d516ee9ed23f5bef author: prettyboy date: 2020-05-28T12:04:46+03:00 revision: 6879742 Dump extra siginfo if term signal is received issue:DEVTOOLSSUPPORT-1110 REVIEW: 1279268 --- contrib/deprecated/python/faulthandler/faulthandler.c (b4ffd42d61e5a2398623b2c73b681b72896da86b) +++ contrib/deprecated/python/faulthandler/faulthandler.c (1a1c8a87cb6e966c8d716a90d516ee9ed23f5bef) @@ -43,6 +43,8 @@ /* defined in traceback.c */ extern Py_ssize_t _Py_write_noraise(int fd, const char *buf, size_t count); +extern void dump_decimal(int fd, int value); +extern void reverse_string(char *text, const size_t len); /* cast size_t to int because write() takes an int on Windows (anyway, the length is smaller than 30 characters) */ @@ -378,6 +380,81 @@ faulthandler_fatal_error(int signum) raise(signum); } +static size_t +uitoa(size_t val, char* ss) { + char* start = ss; + size_t len = 0; + do { + *ss = '0' + (val % 10); + val /= 10; + ss++; len++; + } while (val); + reverse_string(start, len); + return len; +} + +static void +read_proc_exe(pid_t pid, char* buff, size_t len) { + char pathname[32] = {0}; + strcpy(pathname, "/proc/"); + size_t pos = uitoa(pid, &pathname[6]) + 6; + strcpy(&pathname[pos], "/exe"); + + ssize_t l = readlink(pathname, buff, len); + if (l > 0) { + // readlink() does not append a null byte to buf + buff[l] = '\0'; + } else { + strncpy(buff, "unknown_program", len); + } +} + +static void +faulthandler_fatal_error_siginfo(int signum, siginfo_t* siginfo, void* ctx) +{ + const int fd = fatal_error.fd; + int save_errno = errno; + + if (!fatal_error.enabled) + return; + + PUTS(fd, "\n*** Signal {si_signo="); + dump_decimal(fd, siginfo->si_signo); + + PUTS(fd, ", si_code="); + dump_decimal(fd, siginfo->si_code); + switch (siginfo->si_code) { + case SEGV_ACCERR: PUTS(fd, " SEGV_ACCERR"); break; + case SEGV_MAPERR: PUTS(fd, " SEGV_MAPERR"); break; + case SI_KERNEL: PUTS(fd, " SI_KERNEL"); break; + case SI_TIMER: PUTS(fd, " SI_TIMER"); break; + case SI_TKILL: PUTS(fd, " SI_TKILL"); break; + case SI_USER: PUTS(fd, " SI_USER"); break; + } + + if (siginfo->si_pid > 0) { + PUTS(fd, ", si_pid="); + dump_decimal(fd, siginfo->si_pid); + PUTS(fd, " "); + char buffer[PATH_MAX] = {0}; + read_proc_exe(siginfo->si_pid, &buffer[0], PATH_MAX - 1); + PUTS(fd, &buffer[0]); + } + + PUTS(fd, ", si_uid="); + dump_decimal(fd, siginfo->si_uid); + + PUTS(fd, "} received by proc {pid="); + dump_decimal(fd, getpid()); + PUTS(fd, ", uid="); + dump_decimal(fd, getuid()); + PUTS(fd, "} ***\n"); + + faulthandler_fatal_error(signum); + + errno = save_errno; +} + #ifdef MS_WINDOWS extern void _Py_dump_hexadecimal(int fd, unsigned long value, size_t bytes); @@ -489,11 +566,17 @@ faulthandler_enable(PyObject *self, PyObject *args, PyObject *kwargs) for (i=0; i < faulthandler_nsignals; i++) { handler = &faulthandler_handlers[i]; #ifdef HAVE_SIGACTION + action.sa_flags = 0; +#ifdef USE_SIGINFO + action.sa_handler = faulthandler_fatal_error_siginfo; + action.sa_flags |= SA_SIGINFO; +#else action.sa_handler = faulthandler_fatal_error; +#endif sigemptyset(&action.sa_mask); /* Do not prevent the signal from being received from within its own signal handler */ - action.sa_flags = SA_NODEFER; + action.sa_flags |= SA_NODEFER; #ifdef HAVE_SIGALTSTACK if (stack.ss_sp != NULL) { /* Call the signal handler on an alternate signal stack --- contrib/deprecated/python/faulthandler/traceback.c (b4ffd42d61e5a2398623b2c73b681b72896da86b) +++ contrib/deprecated/python/faulthandler/traceback.c (1a1c8a87cb6e966c8d716a90d516ee9ed23f5bef) @@ -45,7 +45,7 @@ _Py_write_noraise(int fd, const char *buf, size_t count) This function is signal safe. */ -static void +void reverse_string(char *text, const size_t len) { char tmp; @@ -59,17 +59,17 @@ reverse_string(char *text, const size_t len) } } -/* Format an integer in range [0; 999999] to decimal, +/* Format an integer in range [0; 999999999] to decimal, and write it into the file fd. This function is signal safe. */ -static void +void dump_decimal(int fd, int value) { - char buffer[7]; + char buffer[10]; int len; - if (value < 0 || 999999 < value) + if (value < 0 || 999999999 < value) return; len = 0; do {