|
From: Pavel R. <plr...@gm...> - 2020-03-06 02:46:52
|
Hello,
I've been debugging an issue with software behaving differently under
Valgrind and natively. It turns out there is a subtle difference in
signal handling. Without Valgrind, setting a signal handler to SIG_IGN
clears pending signal even if the previous handler was SIG_IGN. Under
Valdrind, the signal remains pending.
I wrote a short program that demonstrated the issue.
Native output:
Signal: not pending, unblocked, handled
Blocking signal
Signal: not pending, blocked, handled
Ignoring signal
Signal: not pending, blocked, ignored
Raising signal
Signal: pending, blocked, ignored
Ignoring signal
Signal: not pending, blocked, ignored
Finished
Output in Valgrind:
Signal: not pending, unblocked, handled
Blocking signal
Signal: not pending, blocked, handled
Ignoring signal
Signal: not pending, blocked, ignored
Raising signal
Signal: pending, blocked, ignored
Ignoring signal
Signal: pending, blocked, ignored
Finished
Please note "pending" at the end.
I don't know which behavior is correct, but I would appreciate if
Valgrind followed the host system more closely.
I'm running Ubuntu 18.04, x86_64, Linux kernel 5.3.0-40-generic. Both
Valgrind 3.15.0 and today's git exhibit the same behavior.
#include <signal.h>
#include <stdio.h>
int signal_number = SIGINT;
void report_status(const char *message)
{
sigset_t pending_mask, blocked_mask;
struct sigaction sa_current;
sigpending(&pending_mask);
sigprocmask(SIG_SETMASK, NULL, &blocked_mask);
sigaction(signal_number, NULL, &sa_current);
printf("Signal: %s, %s, %s\n",
sigismember(&pending_mask, signal_number) ? "pending" : "not pending",
sigismember(&blocked_mask, signal_number) ? "blocked" : "unblocked",
sa_current.sa_handler == SIG_IGN ? "ignored" : "handled");
printf("%s\n", message);
}
int main()
{
struct sigaction sa_ignoring;
sigset_t blocking_mask;
sa_ignoring.sa_handler = SIG_IGN;
sigemptyset(&sa_ignoring.sa_mask);
sa_ignoring.sa_flags = SA_RESTART;
report_status("Blocking signal");
sigemptyset(&blocking_mask);
sigaddset(&blocking_mask, signal_number);
sigprocmask(SIG_BLOCK, &blocking_mask, NULL);
report_status("Ignoring signal");
sigaction(signal_number, &sa_ignoring, NULL);
report_status("Raising signal");
raise(signal_number);
report_status("Ignoring signal");
sigaction(signal_number, &sa_ignoring, NULL);
report_status("Finished");
return 0;
}
--
Regards,
Pavel Roskin
|