[PATCH] display mask on enter to sigreturn, not exit
Denys Vlasenko
dvlasenk at redhat.com
Wed Jan 11 13:56:27 UTC 2012
On 01/11/2012 01:27 AM, Jamie Lokier wrote:
> Denys Vlasenko wrote:
>> On 01/10/2012 09:19 PM, Dmitry V. Levin wrote:
>>>> While at it, I made it so that we do display returned value/errno.
>>>> I see no point in hiding it and showing uninformative "= ?" instead.
>>>
>>> Is there any actual difference? Is there any case when sigreturn() may
>>> "return" something different from EINTR?
>>
>> Yes. -EINTR return means that the interrupted system call won't be restarted.
>> It looks like this:
>>
>> rt_sigsuspend([ABRT]) = ? ERESTARTNOHAND (To be restarted)
>> --- {si_signo=SIGALRM, si_code=SI_KERNEL, si_value={int=134513920, ptr=0x8048500}} (Alarm clock) ---
>> alarm(1) = 0
>> sigreturn() (mask now [ABRT]) = -1 EINTR (Interrupted system call)
>>
>> Whereas the case when syscall is restarted looks like this:
>>
>> read(0, 0x8121750, 1024) = ? ERESTARTSYS (To be restarted)
>> --- {si_signo=SIGALRM, si_code=SI_KERNEL, si_value={int=134513920, ptr=0x8048500}} (Alarm clock) ---
>> alarm(1) = 0
>> sigreturn() (mask now [ABRT]) = 3
>> read(0, 0x8121750, 1024)...
>>
>> This is a potentially useful bit of information we weren't showing.
>
> You are showing it earlier as ERESTARTNOHAND vs. ERESTARTSYS.
Which reminds me: there is widespread confusion about exact meaning
of ERESTARTxyz codes. We show all four of them as "(To be restarted)".
I looked at kernel code and I propose the following
change which prints better explanation of these codes,
and contains verbose comments which explain *why* we display
code that way - or else someone confused
is bound to come later and mangle them again:
diff -d -urpN strace.5/syscall.c strace.6/syscall.c
--- strace.5/syscall.c 2012-01-09 13:24:57.122811923 +0100
+++ strace.6/syscall.c 2012-01-11 14:53:52.939894558 +0100
@@ -2412,17 +2412,51 @@ 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 bit is set; otherwise, system call fails 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 the syscall.
+ * SA_RESTART is ignored (assumed not set) similarly to ERESTARTNOHAND.
+ */
+ tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)");
break;
#endif /* LINUX */
default:
--
vda
More information about the Strace-devel
mailing list