@@ -156,6 +156,7 @@ pid_t child_pid = -1;
156156
157157static volatile sig_atomic_t received_SIGCHLD = 0 ;
158158static volatile sig_atomic_t received_signal = -1 ;
159+ static volatile sig_atomic_t error_in_signalhandler = 0 ;
159160
160161int child_pipefd[3 ][2 ];
161162int child_redirfd[3 ];
@@ -192,7 +193,7 @@ struct option const long_opts[] = {
192193void warning ( const char *, ...) __attribute__((format (printf, 1 , 2 )));
193194void verbose ( const char *, ...) __attribute__((format (printf, 1 , 2 )));
194195void 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
197198void warning (const char *format, ...)
198199{
@@ -226,6 +227,25 @@ void verbose(const char *format, ...)
226227 va_end (ap);
227228}
228229
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+
229249void error (int errnum, const char *format, ...)
230250{
231251 // Silently ignore errors that happen while handling other errors.
@@ -674,43 +694,47 @@ void terminate(int sig)
674694 sigact.sa_handler = SIG_DFL;
675695 sigact.sa_flags = 0 ;
676696 if ( sigemptyset (&sigact.sa_mask )!=0 ) {
677- warning (" could not initialize signal mask" );
697+ warning_from_signalhandler (" could not initialize signal mask" );
678698 }
679699 if ( sigaction (SIGTERM,&sigact,nullptr )!=0 ) {
680- warning (" could not restore signal handler" );
700+ warning_from_signalhandler (" could not restore signal handler" );
681701 }
682702 if ( sigaction (SIGALRM,&sigact,nullptr )!=0 ) {
683- warning (" could not restore signal handler" );
703+ warning_from_signalhandler (" could not restore signal handler" );
684704 }
685705
686706 if ( sig==SIGALRM ) {
687707 if (runpipe_pid > 0 ) {
688- warning (" sending SIGUSR1 to runpipe with pid %d " , runpipe_pid );
708+ warning_from_signalhandler (" sending SIGUSR1 to runpipe" );
689709 kill (runpipe_pid, SIGUSR1);
690710 }
691711
692712 walllimit_reached |= hard_timelimit;
693- warning (" timelimit exceeded (hard wall time): aborting command" );
713+ warning_from_signalhandler (" timelimit exceeded (hard wall time): aborting command" );
694714 } else {
695- warning (" received signal %d : aborting command" ,sig );
715+ warning_from_signalhandler (" received signal: aborting command" );
696716 }
697717
698718 received_signal = sig;
699719
700720 /* First try to kill graciously, then hard.
701721 Don't report an already exited process as error. */
702- verbose (" sending SIGTERM" );
722+ verbose_from_signalhandler (" sending SIGTERM" );
703723 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 ;
705727 }
706728
707729 /* Prefer nanosleep over sleep because of higher resolution and
708730 it does not interfere with signals. */
709731 nanosleep (&killdelay,nullptr );
710732
711- verbose (" sending SIGKILL" );
733+ verbose_from_signalhandler (" sending SIGKILL" );
712734 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 ;
714738 }
715739
716740 /* Wait another while to make sure the process is killed by now. */
@@ -1465,6 +1489,9 @@ int main(int argc, char **argv)
14651489
14661490 int r = pselect (nfds+1 , &readfds, nullptr , NULL , NULL , &emptymask);
14671491 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+ }
14681495
14691496 if ( received_SIGCHLD || received_signal == SIGALRM ) {
14701497 pid_t pid;
0 commit comments