strace: rewrite restart error handling without sigsetjmp/siglongjmp

Further simplify and optimize error handling of the delay signal handler
by replacing sigsetjmp/siglongjmp mechanism with an error flag.

* strace.c: Do not include <setjmp.h>.
(restart_failed): New volatile variable.
(timer_jmp_buf): Remove.
(next_event): Cache is_delay_timer_created() return value,
remove sigsetjmp invocation, check restart_failed instead.
(timer_sighandler): Replace siglongjmp with setting restart_failed.
This commit is contained in:
Дмитрий Левин 2018-03-23 00:20:33 +00:00
parent 4976ce2f31
commit f56a3feb32

View File

@ -34,7 +34,6 @@
#include <limits.h>
#include <fcntl.h>
#include "ptrace.h"
#include <setjmp.h>
#include <signal.h>
#include <sys/resource.h>
#include <sys/wait.h>
@ -168,12 +167,11 @@ static void cleanup(void);
static void interrupt(int sig);
#ifdef HAVE_SIG_ATOMIC_T
static volatile sig_atomic_t interrupted;
static volatile sig_atomic_t interrupted, restart_failed;
#else
static volatile int interrupted;
static volatile int interrupted, restart_failed;
#endif
static jmp_buf timer_jmp_buf;
static sigset_t timer_set;
static void timer_sighandler(int);
@ -2238,6 +2236,8 @@ next_event(int *pstatus, siginfo_t *si)
return TE_BREAK;
}
const bool unblock_delay_timer = is_delay_timer_created();
/*
* The window of opportunity to handle expirations
* of the delay timer opens here.
@ -2245,16 +2245,8 @@ next_event(int *pstatus, siginfo_t *si)
* Unblock the signal handler for the delay timer
* iff the delay timer is already created.
*/
if (is_delay_timer_created()) {
if (sigsetjmp(timer_jmp_buf, 1)) {
/*
* restart_delayed_tcbs() forwarded an error
* from dispatch_event().
*/
return TE_BREAK;
}
if (unblock_delay_timer)
sigprocmask(SIG_UNBLOCK, &timer_set, NULL);
}
/*
* If the delay timer has expired, then its expiration
@ -2272,11 +2264,15 @@ next_event(int *pstatus, siginfo_t *si)
* of the delay timer closes here.
*
* Block the signal handler for the delay timer
* iff the delay timer is already created.
* iff it was unblocked earlier.
*/
if (is_delay_timer_created())
if (unblock_delay_timer) {
sigprocmask(SIG_BLOCK, &timer_set, NULL);
if (restart_failed)
return TE_BREAK;
}
if (pid < 0) {
if (wait_errno == EINTR)
return TE_NEXT;
@ -2611,10 +2607,13 @@ restart_delayed_tcbs(void)
static void
timer_sighandler(int sig)
{
if (restart_failed)
return;
int saved_errno = errno;
if (!restart_delayed_tcbs())
siglongjmp(timer_jmp_buf, 1);
restart_failed = 1;
errno = saved_errno;
}