Index: usr.bin/truss/setup.c =================================================================== --- usr.bin/truss/setup.c +++ usr.bin/truss/setup.c @@ -144,6 +144,39 @@ } /* + * A no-op signal handler so we can break out of wait. + */ +static void +trapalrm(int signo __unused) +{ + return; +} + +/* + * Prints names and arguments of any threads currently in a syscall. + */ +static void +print_sleeping_threads(struct trussinfo *info) +{ + struct procinfo *p; + LIST_FOREACH(p, &info->proclist, entries) { + struct threadinfo *t; + LIST_FOREACH(t, &p->threadlist, entries) { + if (t->in_syscall) { + info->curthread = t; + if (info->flags & (RELATIVETIMESTAMPS | + ABSOLUTETIMESTAMPS)) + clock_gettime(CLOCK_REALTIME, + &t->after); + print_syscall(info); + fprintf(info->outfile, " ...sleeping\n"); + } + } + } +} + + +/* * Determine the ABI. This is called after every exec, and when * a process is first monitored. */ @@ -482,6 +515,7 @@ } } + t->in_syscall = 0; print_syscall_ret(info, errorp, retval); free_syscall(t); @@ -610,17 +644,55 @@ siginfo_t si; int pending_signal; + signal(SIGALRM, trapalrm); + siginterrupt(SIGALRM, 1); + while (!LIST_EMPTY(&info->proclist)) { + struct procinfo *p; + int in_syscall = 0; + if (detaching) { detach_all_procs(info); return; } - if (waitid(P_ALL, 0, &si, WTRAPPED | WEXITED) == -1) { - if (errno == EINTR) + /* Count up all threads waiting in a syscall */ + LIST_FOREACH(p, &info->proclist, entries) { + struct threadinfo *t; + LIST_FOREACH(t, &p->threadlist, entries) { + if (t->in_syscall) + in_syscall++; + } + } + + if (in_syscall) + alarm(2); + + while (waitid(P_ALL, 0, &si, WTRAPPED | WEXITED) == -1) { + if (errno == EINTR) { + if (detaching) + break; + if (in_syscall) { + /* + * The 2-second timer interrupted + * us, so we must be waiting on slow + * syscalls. Print their names and + * continue waiting, this time + * forever. + */ + print_sleeping_threads(info); + fflush(info->outfile); + alarm(0); + } continue; + } err(1, "Unexpected error from waitid"); } + if (detaching) + continue; + + if (in_syscall) + alarm(0); assert(si.si_signo == SIGCHLD); Index: usr.bin/truss/syscalls.c =================================================================== --- usr.bin/truss/syscalls.c +++ usr.bin/truss/syscalls.c @@ -2134,7 +2134,7 @@ len += fprintf(trussinfo->outfile, "%s", s_args[i]); else len += fprintf(trussinfo->outfile, - ""); + t->in_syscall ? "" : ""); len += fprintf(trussinfo->outfile, "%s", i < (nargs - 1) ? "," : ""); }