Sat 25 Jan 2014 12:38:16 AM UTC, original submission:
Hi, there is possible race condition in job.c in function set_child_handler_action_flags when it is called to set alarm. There is short period of time, when alarm is set, but handler is not set; sometimes this may kill make process.
The code fragment:
http://git.savannah.gnu.org/cgit/make.git/tree/job.c#n1093
set_child_handler_action_flags (int set_handler, int set_alarm)
{
....
#if defined SIGALRM
if (set_alarm)
{
/* If we're about to enter the read(), set an alarm to wake up in a
second so we can check if the load has dropped and we can start more
work. On the way out, turn off the alarm and set SIG_DFL. */
alarm (set_handler ? 1 : 0);
sa.sa_handler = set_handler ? job_noop : SIG_DFL;
sa.sa_flags = 0;
sigaction (SIGALRM, &sa, NULL);
}
#endif
}
#endif
If we are setting alarm, the order of calls is:
alarm(1);
sa.sa_handler=job_noop;
sigaction(SIGALRM, &sa, NULL);
And when we are unsetting the alarm, the order is
alarm(0);
sa.sa_handler=SIG_DFL; // DFL is kill
sigaction(SIGALRM, &sa, NULL);
So, for the setting of alarm, when used on very slow machine or on very loaded machine there is probability that make process will do alarm(1) and then will be descheduled from CPU for time of more than 1 real time second. SIGALRM will be generated and delivered before sigaction call, killing the make process.
I think the better way of setting the alarm is to register handler BEFORE setting alarm and deregister it AFTER disabling alarm, like
if(set_handler) {
sa.sa_handler = job_noop;
sa.sa_flags = 0;
sigaction (SIGALRM, &sa, NULL);
alarm (1);
} else {
alarm (0);
sa.sa_handler = SIG_DFL;
sa.sa_flags = 0;
sigaction (SIGALRM, &sa, NULL);
}
Thanks!
|