Make strace somewhat resilient against process disappearing
under its claws. Prime example is sudden SIGKILL.
Fixes RH#472053
diff --git a/syscall.c b/syscall.c
index c2940c3..7d570d1 100644
--- a/syscall.c
+++ b/syscall.c
@@ -2319,28 +2319,30 @@
{
int sys_res;
struct timeval tv;
- int res;
-
- /* Measure the exit time as early as possible to avoid errors. */
- if (dtime && (tcp->flags & TCB_INSYSCALL))
- gettimeofday(&tv, NULL);
-
- res = get_scno(tcp);
- if (res != 1)
- return res;
-
- res = syscall_fixup(tcp);
- if (res != 1)
- return res;
+ int res, scno_good;
if (tcp->flags & TCB_INSYSCALL) {
long u_error;
- res = get_error(tcp);
- if (res != 1)
- return res;
- internal_syscall(tcp);
- if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
+ /* Measure the exit time as early as possible to avoid errors. */
+ if (dtime)
+ gettimeofday(&tv, NULL);
+
+ scno_good = res = get_scno(tcp);
+ if (res == 0)
+ return res;
+ if (res == 1)
+ res = syscall_fixup(tcp);
+ if (res == 0)
+ return res;
+ if (res == 1)
+ res = get_error(tcp);
+ if (res == 0)
+ return res;
+ if (res == 1)
+ internal_syscall(tcp);
+
+ if (res == 1 && tcp->scno >= 0 && tcp->scno < nsyscalls &&
!(qual_flags[tcp->scno] & QUAL_TRACE)) {
tcp->flags &= ~TCB_INSYSCALL;
return 0;
@@ -2349,7 +2351,9 @@
if (tcp->flags & TCB_REPRINT) {
printleader(tcp);
tprintf("<... ");
- if (tcp->scno >= nsyscalls || tcp->scno < 0)
+ if (scno_good != 1)
+ tprintf("????");
+ else if (tcp->scno >= nsyscalls || tcp->scno < 0)
tprintf("syscall_%lu", tcp->scno);
else
tprintf("%s", sysent[tcp->scno].sys_name);
@@ -2359,6 +2363,13 @@
if (cflag)
return count_syscall(tcp, &tv);
+ if (res != 1) {
+ tprintf(") ");
+ tabto(acolumn);
+ tcp->flags &= ~TCB_INSYSCALL;
+ return res;
+ }
+
if (tcp->scno >= nsyscalls || tcp->scno < 0
|| (qual_flags[tcp->scno] & QUAL_RAW))
sys_res = printargs(tcp);
@@ -2463,9 +2474,35 @@
}
/* Entering system call */
- res = syscall_enter(tcp);
- if (res != 1)
+ scno_good = res = get_scno(tcp);
+ if (res == 0)
return res;
+ if (res == 1)
+ res = syscall_fixup(tcp);
+ if (res == 0)
+ return res;
+ if (res == 1)
+ res = syscall_enter(tcp);
+ if (res == 0)
+ return res;
+
+ if (res != 1) {
+ printleader(tcp);
+ tcp->flags &= ~TCB_REPRINT;
+ tcp_last = tcp;
+ if (scno_good != 1)
+ tprintf("????" /* anti-trigraph gap */ "(");
+ else if (tcp->scno >= nsyscalls || tcp->scno < 0)
+ tprintf("syscall_%lu(", tcp->scno);
+ else
+ tprintf("%s(", sysent[tcp->scno].sys_name);
+ /*
+ * " <unavailable>" will be added later by the code which
+ * detects ptrace errors.
+ */
+ tcp->flags |= TCB_INSYSCALL;
+ return res;
+ }
switch (known_scno(tcp)) {
#ifdef SYS_socket_subcall