diff options
author | Denys Vlasenko <dvlasenk@redhat.com> | 2012-01-12 11:26:34 +0100 |
---|---|---|
committer | Denys Vlasenko <dvlasenk@redhat.com> | 2012-01-12 11:26:34 +0100 |
commit | fe585656f8d0c6ac7298df22fce0d9ee0935e264 (patch) | |
tree | 85c3fa93ea2beed9d98e0286b491c8895e421deb | |
parent | 3cc943825e3aa0d3f2681be33164412113cab5ab (diff) | |
download | strace-fe585656f8d0c6ac7298df22fce0d9ee0935e264.tar.gz |
Make ERESTARTxyz messages more descriptive
There is widespread confusion about exact meaning
of ERESTARTxyz codes. Before this change, we were showing
all four of them the same: as "(To be restarted)".
This change prints better explanations for these codes,
and contains verbose comments which explain *why* we display
codes that way - or else someone confused
is bound to come later and mangle them again.
New messages are:
ERESTARTSYS (To be restarted if SA_RESTART is set)
ERESTARTNOINTR (To be restarted)
ERESTARTNOHAND (Interrupted by signal)
ERESTART_RESTARTBLOCK (Interrupted by signal)
* syscall.c (trace_syscall_exiting): Make ERESTARTxyz messages
more descriptive.
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
-rw-r--r-- | syscall.c | 46 |
1 files changed, 43 insertions, 3 deletions
@@ -2412,17 +2412,57 @@ trace_syscall_exiting(struct tcb *tcp) else if (!(sys_res & RVAL_NONE) && u_error) { switch (u_error) { #ifdef LINUX + /* Blocked signals do not interrupt any syscalls. + * In this case syscalls don't return ERESTARTfoo codes. + * + * Deadly signals set to SIG_DFL interrupt syscalls + * and kill the process regardless of which of the codes below + * is returned by the interrupted syscall. + * In some cases, kernel forces a kernel-generated deadly + * signal to be unblocked and set to SIG_DFL (and thus cause + * death) if it is blocked or SIG_IGNed: for example, SIGSEGV + * or SIGILL. (The alternative is to leave process spinning + * forever on the faulty instruction - not useful). + * + * SIG_IGNed signals and non-deadly signals set to SIG_DFL + * (for example, SIGCHLD, SIGWINCH) interrupt syscalls, + * but kernel will always restart them. + */ case ERESTARTSYS: - tprints("= ? ERESTARTSYS (To be restarted)"); + /* Most common type of signal-interrupted syscall exit code. + * The system call will be restarted with the same arguments + * if SA_RESTART is set; otherwise, it will fail with EINTR. + */ + tprints("= ? ERESTARTSYS (To be restarted if SA_RESTART is set)"); break; case ERESTARTNOINTR: + /* Rare. For example, fork() returns this if interrupted. + * SA_RESTART is ignored (assumed set): the restart is unconditional. + */ tprints("= ? ERESTARTNOINTR (To be restarted)"); break; case ERESTARTNOHAND: - tprints("= ? ERESTARTNOHAND (To be restarted)"); + /* pause(), rt_sigsuspend() etc use this code. + * SA_RESTART is ignored (assumed not set): + * syscall won't restart (will return EINTR instead) + * even after signal with SA_RESTART set. + * However, after SIG_IGN or SIG_DFL signal it will. + */ + tprints("= ? ERESTARTNOHAND (Interrupted by signal)"); break; case ERESTART_RESTARTBLOCK: - tprints("= ? ERESTART_RESTARTBLOCK (To be restarted)"); + /* Syscalls like nanosleep(), poll() which can't be + * restarted with their original arguments use this + * code. Kernel will execute restart_syscall() instead, + * which changes arguments before restarting syscall. + * SA_RESTART is ignored (assumed not set) similarly + * to ERESTARTNOHAND. (Kernel can't honor SA_RESTART + * since restart data is saved in "restart block" + * in task struct, and if signal handler uses a syscall + * which in turn saves another such restart block, + * old data is lost and restart becomes impossible) + */ + tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)"); break; #endif /* LINUX */ default: |