]> granicus.if.org Git - strace/commitdiff
Show the syscall name in "resuming interrupted call" message
authorDenys Vlasenko <dvlasenk@redhat.com>
Sat, 21 Mar 2015 16:51:52 +0000 (17:51 +0100)
committerDenys Vlasenko <dvlasenk@redhat.com>
Sat, 21 Mar 2015 17:04:53 +0000 (18:04 +0100)
When signal is received, or if we have attached to a process,
current syscall (if process is in one) gets restarted.

Some syscalls are restarted via "restart_syscall()" mechanism.
On such sycalls, we don't show _which_ syscall gets restarted.

IOW: users want to see "resuming interrupted nanosleep"
instead of "resuming interrupted call" when they attach to "sleep 999".

Kernel does expose this information. The only thing we need is
to fetch syscall# on attach, and save it.

This patch does this. It adds tcp->s_prev_ent, which is
a pointer to struct_sysent of the previous syscall of this tracee.
It can be NULL.

sys_restart_syscall() is made to use it when the message is generated.

To similarly handle restart_syscall() *after signals*, not just
on attach, on each syscall exit patch saves exited syscall's data
in the same member (tcp->s_prev_ent).

Example:

    $ sleep 3 & strace -p $!
    Process 8728 attached
    restart_syscall(<... resuming interrupted nanosleep ...>) = 0
    _exit(0)                                = ?
    +++ exited with 0 +++

Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
defs.h
signal.c
strace.c
syscall.c

diff --git a/defs.h b/defs.h
index dad4fe8b2590a2ddf87bdbb56b1adc3d122b9794..9e269c7a95f0a6205f908e78b49dcb099c31feb6 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -243,6 +243,7 @@ struct tcb {
        FILE *outf;             /* Output file for this process */
        const char *auxstr;     /* Auxiliary info from syscall (see RVAL_STR) */
        const struct_sysent *s_ent; /* sysent[scno] or dummy struct for bad scno */
+       const struct_sysent *s_prev_ent; /* for "resuming interrupted SYSCALL" msg */
        struct timeval stime;   /* System time usage as of last process wait */
        struct timeval dtime;   /* Delta for system time usage */
        struct timeval etime;   /* Syscall entry time */
@@ -418,6 +419,7 @@ extern void call_summary(FILE *);
 
 extern void clear_regs(void);
 extern void get_regs(pid_t pid);
+extern int get_scno(struct tcb *tcp);
 
 extern int umoven(struct tcb *, long, unsigned int, char *);
 #define umove(pid, addr, objp) \
index 867e1563bd7d9f34a30fd5303877dd03200a8f2f..5ffd0d06e88b53e6f6a4650b31df34b375ba8c64 100644 (file)
--- a/signal.c
+++ b/signal.c
@@ -1056,8 +1056,13 @@ int sys_rt_sigtimedwait(struct tcb *tcp)
 int
 sys_restart_syscall(struct tcb *tcp)
 {
-       if (entering(tcp))
-               tprints("<... resuming interrupted call ...>");
+       if (entering(tcp)) {
+               tprintf("<... resuming interrupted %s ...>",
+                       tcp->s_prev_ent
+                       ? tcp->s_prev_ent->sys_name
+                       : "system call"
+               );
+       }
        return 0;
 }
 
index b714255f41e1b6aeb9af95c4533520932e04d65b..bf5531c5e707a30de2ae779bcec8e3963ce237ff 100644 (file)
--- a/strace.c
+++ b/strace.c
@@ -2153,6 +2153,8 @@ trace(void)
        if (tcp->flags & TCB_STARTUP) {
                if (!startup_tcb(tcp))
                        return false;
+               if (get_scno(tcp) == 1)
+                       tcp->s_prev_ent = tcp->s_ent;
        }
 
        sig = WSTOPSIG(status);
index b37f43a6260af9245c257e4799aa9d692620fdd1..33b22ecc3d56b5f14f33061fe11f22cebe12ca9a 100644 (file)
--- a/syscall.c
+++ b/syscall.c
@@ -1127,7 +1127,7 @@ get_regs(pid_t pid)
  * other: error, trace_syscall_entering() should print error indicator
  *    ("????" etc) and bail out.
  */
-static int
+int
 get_scno(struct tcb *tcp)
 {
        long scno = 0;
@@ -2239,6 +2239,7 @@ trace_syscall_exiting(struct tcb *tcp)
        }
        printing_tcp = tcp;
 
+       tcp->s_prev_ent = NULL;
        if (res != 1) {
                /* There was error in one of prior ptrace ops */
                tprints(") ");
@@ -2248,6 +2249,7 @@ trace_syscall_exiting(struct tcb *tcp)
                tcp->flags &= ~TCB_INSYSCALL;
                return res;
        }
+       tcp->s_prev_ent = tcp->s_ent;
 
        sys_res = 0;
        if (tcp->qual_flg & QUAL_RAW) {