@@ -156,6 +156,7 @@ pid_t child_pid = -1;
156
156
157
157
static volatile sig_atomic_t received_SIGCHLD = 0 ;
158
158
static volatile sig_atomic_t received_signal = -1 ;
159
+ static volatile sig_atomic_t error_in_signalhandler = 0 ;
159
160
160
161
int child_pipefd[3 ][2 ];
161
162
int child_redirfd[3 ];
@@ -192,7 +193,7 @@ struct option const long_opts[] = {
192
193
void warning ( const char *, ...) __attribute__((format (printf, 1 , 2 )));
193
194
void verbose ( const char *, ...) __attribute__((format (printf, 1 , 2 )));
194
195
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 )));
196
197
197
198
void warning (const char *format, ...)
198
199
{
@@ -226,6 +227,25 @@ void verbose(const char *format, ...)
226
227
va_end (ap);
227
228
}
228
229
230
+ // These functions are called from signal handlers, so they
231
+ // must only call async-signal-safe functions.
232
+ // write() is async-signal-safe, printf and variants are not.
233
+ void verbose_from_signalhandler (const char * msg)
234
+ {
235
+ if (!be_quiet && be_verbose) {
236
+ write (STDERR_FILENO, msg, strlen (msg));
237
+ }
238
+ }
239
+
240
+ void warning_from_signalhandler (const char * msg)
241
+ {
242
+ if (!be_quiet) {
243
+ // Do not include timing here, as it wouldn't be safe from a signalhandler.
244
+ // TODO: Consider rewriting using clock_gettime in the future.
245
+ write (STDERR_FILENO, msg, strlen (msg));
246
+ }
247
+ }
248
+
229
249
void error (int errnum, const char *format, ...)
230
250
{
231
251
// Silently ignore errors that happen while handling other errors.
@@ -674,43 +694,47 @@ void terminate(int sig)
674
694
sigact.sa_handler = SIG_DFL;
675
695
sigact.sa_flags = 0 ;
676
696
if ( sigemptyset (&sigact.sa_mask )!=0 ) {
677
- warning (" could not initialize signal mask" );
697
+ warning_from_signalhandler (" could not initialize signal mask" );
678
698
}
679
699
if ( sigaction (SIGTERM,&sigact,nullptr )!=0 ) {
680
- warning (" could not restore signal handler" );
700
+ warning_from_signalhandler (" could not restore signal handler" );
681
701
}
682
702
if ( sigaction (SIGALRM,&sigact,nullptr )!=0 ) {
683
- warning (" could not restore signal handler" );
703
+ warning_from_signalhandler (" could not restore signal handler" );
684
704
}
685
705
686
706
if ( sig==SIGALRM ) {
687
707
if (runpipe_pid > 0 ) {
688
- warning (" sending SIGUSR1 to runpipe with pid %d " , runpipe_pid );
708
+ warning_from_signalhandler (" sending SIGUSR1 to runpipe" );
689
709
kill (runpipe_pid, SIGUSR1);
690
710
}
691
711
692
712
walllimit_reached |= hard_timelimit;
693
- warning (" timelimit exceeded (hard wall time): aborting command" );
713
+ warning_from_signalhandler (" timelimit exceeded (hard wall time): aborting command" );
694
714
} else {
695
- warning (" received signal %d : aborting command" ,sig );
715
+ warning_from_signalhandler (" received signal: aborting command" );
696
716
}
697
717
698
718
received_signal = sig;
699
719
700
720
/* First try to kill graciously, then hard.
701
721
Don't report an already exited process as error. */
702
- verbose (" sending SIGTERM" );
722
+ verbose_from_signalhandler (" sending SIGTERM" );
703
723
if ( kill (-child_pid,SIGTERM)!=0 && errno!=ESRCH ) {
704
- error (errno," sending SIGTERM to command" );
724
+ warning_from_signalhandler (" error sending SIGTERM to command" );
725
+ error_in_signalhandler = 1 ;
726
+ return ;
705
727
}
706
728
707
729
/* Prefer nanosleep over sleep because of higher resolution and
708
730
it does not interfere with signals. */
709
731
nanosleep (&killdelay,nullptr );
710
732
711
- verbose (" sending SIGKILL" );
733
+ verbose_from_signalhandler (" sending SIGKILL" );
712
734
if ( kill (-child_pid,SIGKILL)!=0 && errno!=ESRCH ) {
713
- error (errno," sending SIGKILL to command" );
735
+ warning_from_signalhandler (" error sending SIGKILL to command" );
736
+ error_in_signalhandler = 1 ;
737
+ return ;
714
738
}
715
739
716
740
/* Wait another while to make sure the process is killed by now. */
@@ -1465,6 +1489,9 @@ int main(int argc, char **argv)
1465
1489
1466
1490
int r = pselect (nfds+1 , &readfds, nullptr , NULL , NULL , &emptymask);
1467
1491
if ( r==-1 && errno!=EINTR ) error (errno," waiting for child data" );
1492
+ if (error_in_signalhandler) {
1493
+ error (errno, " error in signal handler, exiting" );
1494
+ }
1468
1495
1469
1496
if ( received_SIGCHLD || received_signal == SIGALRM ) {
1470
1497
pid_t pid;
0 commit comments