Skip to content

Commit 215bf62

Browse files
committed
Remove functions that are not async-signal-safe from signal handler.
Fixes #3034
1 parent ebe8f21 commit 215bf62

File tree

1 file changed

+33
-11
lines changed

1 file changed

+33
-11
lines changed

judge/runguard.cc

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ pid_t child_pid = -1;
156156

157157
static volatile sig_atomic_t received_SIGCHLD = 0;
158158
static volatile sig_atomic_t received_signal = -1;
159+
static volatile sig_atomic_t error_in_signalhandler = 0;
159160

160161
int child_pipefd[3][2];
161162
int child_redirfd[3];
@@ -192,7 +193,7 @@ struct option const long_opts[] = {
192193
void warning( const char *, ...) __attribute__((format (printf, 1, 2)));
193194
void verbose( const char *, ...) __attribute__((format (printf, 1, 2)));
194195
void error(int, const char *, ...) __attribute__((format (printf, 2, 3)));
195-
void write_meta(const char*, const char *, ...) __attribute__((format (printf, 2, 3)));
196+
void write_meta(const char *, const char *, ...) __attribute__((format (printf, 2, 3)));
196197

197198
void warning(const char *format, ...)
198199
{
@@ -226,6 +227,22 @@ void verbose(const char *format, ...)
226227
va_end(ap);
227228
}
228229

230+
void verbose_from_signalhandler(const char* msg)
231+
{
232+
if (!be_quiet) {
233+
write(STDERR_FILENO, msg, strlen(msg));
234+
}
235+
}
236+
237+
void warning_from_signalhandler(const char* msg)
238+
{
239+
if (!be_quiet && be_verbose) {
240+
// Do not include timing here, as it wouldn't be safe from a signalhandler.
241+
// TODO: Consider rewriting using clock_gettime in the future.
242+
write(STDERR_FILENO, msg, strlen(msg));
243+
}
244+
}
245+
229246
void error(int errnum, const char *format, ...)
230247
{
231248
// Silently ignore errors that happen while handling other errors.
@@ -674,43 +691,45 @@ void terminate(int sig)
674691
sigact.sa_handler = SIG_DFL;
675692
sigact.sa_flags = 0;
676693
if ( sigemptyset(&sigact.sa_mask)!=0 ) {
677-
warning("could not initialize signal mask");
694+
warning_from_signalhandler("could not initialize signal mask");
678695
}
679696
if ( sigaction(SIGTERM,&sigact,nullptr)!=0 ) {
680-
warning("could not restore signal handler");
697+
warning_from_signalhandler("could not restore signal handler");
681698
}
682699
if ( sigaction(SIGALRM,&sigact,nullptr)!=0 ) {
683-
warning("could not restore signal handler");
700+
warning_from_signalhandler("could not restore signal handler");
684701
}
685702

686703
if ( sig==SIGALRM ) {
687704
if (runpipe_pid > 0) {
688-
warning("sending SIGUSR1 to runpipe with pid %d", runpipe_pid);
705+
warning_from_signalhandler("sending SIGUSR1 to runpipe");
689706
kill(runpipe_pid, SIGUSR1);
690707
}
691708

692709
walllimit_reached |= hard_timelimit;
693-
warning("timelimit exceeded (hard wall time): aborting command");
710+
warning_from_signalhandler("timelimit exceeded (hard wall time): aborting command");
694711
} else {
695-
warning("received signal %d: aborting command",sig);
712+
warning_from_signalhandler("received signal: aborting command");
696713
}
697714

698715
received_signal = sig;
699716

700717
/* First try to kill graciously, then hard.
701718
Don't report an already exited process as error. */
702-
verbose("sending SIGTERM");
719+
verbose_from_signalhandler("sending SIGTERM");
703720
if ( kill(-child_pid,SIGTERM)!=0 && errno!=ESRCH ) {
704-
error(errno,"sending SIGTERM to command");
721+
error_in_signalhandler = 1;
722+
return;
705723
}
706724

707725
/* Prefer nanosleep over sleep because of higher resolution and
708726
it does not interfere with signals. */
709727
nanosleep(&killdelay,nullptr);
710728

711-
verbose("sending SIGKILL");
729+
verbose_from_signalhandler("sending SIGKILL");
712730
if ( kill(-child_pid,SIGKILL)!=0 && errno!=ESRCH ) {
713-
error(errno,"sending SIGKILL to command");
731+
error_in_signalhandler = 1;
732+
return;
714733
}
715734

716735
/* Wait another while to make sure the process is killed by now. */
@@ -1465,6 +1484,9 @@ int main(int argc, char **argv)
14651484

14661485
int r = pselect(nfds+1, &readfds, nullptr, NULL, NULL, &emptymask);
14671486
if ( r==-1 && errno!=EINTR ) error(errno,"waiting for child data");
1487+
if (error_in_signalhandler) {
1488+
error(errno, "error in signal handler, exiting");
1489+
}
14681490

14691491
if ( received_SIGCHLD || received_signal == SIGALRM ) {
14701492
pid_t pid;

0 commit comments

Comments
 (0)