@@ -72,6 +72,7 @@ static void sigtrap_handler(int code, siginfo_t *siginfo, void *context);
72
72
static void sigbus_handler (int code, siginfo_t *siginfo, void *context);
73
73
static void sigint_handler (int code, siginfo_t *siginfo, void *context);
74
74
static void sigquit_handler (int code, siginfo_t *siginfo, void *context);
75
+ static void sigterm_handler (int code, siginfo_t *siginfo, void *context);
75
76
76
77
static void common_signal_handler (int code, siginfo_t *siginfo, void *sigcontext, int numParams, ...);
77
78
@@ -91,7 +92,12 @@ struct sigaction g_previous_sigbus;
91
92
struct sigaction g_previous_sigsegv;
92
93
struct sigaction g_previous_sigint;
93
94
struct sigaction g_previous_sigquit;
95
+ struct sigaction g_previous_sigterm;
94
96
97
+ // Pipe used for sending signal notifications to a helper thread
98
+ int g_signalPipe[2 ] = { 0 , 0 };
99
+
100
+ DWORD g_dwExternalSignalHandlerThreadId = 0 ;
95
101
96
102
/* public function definitions ************************************************/
97
103
@@ -178,6 +184,13 @@ void SEHCleanupSignals()
178
184
restore_signal (SIGSEGV, &g_previous_sigsegv);
179
185
restore_signal (SIGINT, &g_previous_sigint);
180
186
restore_signal (SIGQUIT, &g_previous_sigquit);
187
+
188
+ // Only restore if the signal handler thread was started and
189
+ // the previous handler was saved.
190
+ if (g_dwExternalSignalHandlerThreadId != 0 )
191
+ {
192
+ restore_signal (SIGTERM, &g_previous_sigterm);
193
+ }
181
194
}
182
195
183
196
/* internal function definitions **********************************************/
@@ -384,6 +397,60 @@ static void sigquit_handler(int code, siginfo_t *siginfo, void *context)
384
397
kill (gPID , code);
385
398
}
386
399
400
+ /* ++
401
+ Function :
402
+ HandleExternalSignal
403
+
404
+ Write to a pipe to kick off handling of the signal.
405
+
406
+ Parameters :
407
+ signalCode - code of the external signal
408
+
409
+ (no return value)
410
+ --*/
411
+ static void HandleExternalSignal (int signalCode)
412
+ {
413
+ BYTE signalCodeByte = (BYTE)signalCode;
414
+ ssize_t writtenBytes;
415
+ do
416
+ {
417
+ writtenBytes = write (g_signalPipe[1 ], &signalCodeByte, 1 );
418
+ }
419
+ while ((writtenBytes == -1 ) && (errno == EINTR));
420
+
421
+ if (writtenBytes == -1 )
422
+ {
423
+ // Fatal error
424
+ PROCAbort ();
425
+ }
426
+ }
427
+
428
+ /* ++
429
+ Function :
430
+ sigterm_handler
431
+
432
+ handle SIGTERM signal
433
+
434
+ Parameters :
435
+ POSIX signal handler parameter list ("man sigaction" for details)
436
+
437
+ (no return value)
438
+ --*/
439
+ static void sigterm_handler (int code, siginfo_t *siginfo, void *context)
440
+ {
441
+ if (PALIsInitialized ())
442
+ {
443
+ HandleExternalSignal (code);
444
+ }
445
+ else
446
+ {
447
+ if (g_previous_sigterm.sa_sigaction != NULL )
448
+ {
449
+ g_previous_sigterm.sa_sigaction (code, siginfo, context);
450
+ }
451
+ }
452
+ }
453
+
387
454
#ifdef INJECT_ACTIVATION_SIGNAL
388
455
/* ++
389
456
Function :
@@ -624,4 +691,111 @@ void restore_signal(int signal_id, struct sigaction *previousAction)
624
691
}
625
692
}
626
693
694
+ static
695
+ DWORD
696
+ PALAPI
697
+ ExternalSignalHandlerThreadRoutine (
698
+ PVOID
699
+ );
700
+
701
+ PAL_ERROR
702
+ StartExternalSignalHandlerThread (
703
+ CPalThread *pthr)
704
+ {
705
+ PAL_ERROR palError = NO_ERROR;
706
+
707
+ #ifndef DO_NOT_USE_SIGNAL_HANDLING_THREAD
708
+ HANDLE hThread;
709
+
710
+ if (pipe (g_signalPipe) != 0 )
711
+ {
712
+ palError = ERROR_CANNOT_MAKE;
713
+ goto done;
714
+ }
715
+
716
+ palError = InternalCreateThread (
717
+ pthr,
718
+ NULL ,
719
+ 0 ,
720
+ ExternalSignalHandlerThreadRoutine,
721
+ NULL ,
722
+ 0 ,
723
+ SignalHandlerThread, // Want no_suspend variant
724
+ &g_dwExternalSignalHandlerThreadId,
725
+ &hThread
726
+ );
727
+
728
+ if (palError != NO_ERROR)
729
+ {
730
+ ERROR (" Failure creating external signal handler thread (%d)\n " , palError);
731
+ goto done;
732
+ }
733
+
734
+ InternalCloseHandle (pthr, hThread);
735
+
736
+ handle_signal (SIGTERM, sigterm_handler, &g_previous_sigterm);
737
+ #endif // DO_NOT_USE_SIGNAL_HANDLING_THREAD
738
+
739
+ done:
740
+
741
+ return palError;
742
+ }
743
+
744
+ static
745
+ DWORD
746
+ PALAPI
747
+ ExternalSignalHandlerThreadRoutine (
748
+ PVOID
749
+ )
750
+ {
751
+ DWORD dwThreadId;
752
+ bool fContinue = TRUE ;
753
+ HANDLE hThread;
754
+ PAL_ERROR palError = NO_ERROR;
755
+ CPalThread *pthr = InternalGetCurrentThread ();
756
+
757
+ //
758
+ // Wait for a signal to occur
759
+ //
760
+
761
+ while (fContinue )
762
+ {
763
+ BYTE signalCode;
764
+ ssize_t bytesRead;
765
+
766
+ do
767
+ {
768
+ bytesRead = read (g_signalPipe[0 ], &signalCode, 1 );
769
+ }
770
+ while ((bytesRead == -1 ) && (errno == EINTR));
771
+
772
+ if (bytesRead == -1 )
773
+ {
774
+ // Fatal error
775
+ PROCAbort ();
776
+ }
777
+
778
+ switch (signalCode)
779
+ {
780
+ case SIGTERM:
781
+ {
782
+ SEHHandleTerminationRequest ();
783
+ }
784
+
785
+ default :
786
+ ASSERT (" Unexpected signal %d in signal thread\n " , signalCode);
787
+ PROCAbort ();
788
+ break ;
789
+ }
790
+ }
791
+
792
+ //
793
+ // Perform an immediate (non-graceful) shutdown
794
+ //
795
+
796
+ _exit (EXIT_FAILURE);
797
+
798
+ return 0 ;
799
+ }
800
+
627
801
#endif // !HAVE_MACH_EXCEPTIONS
0 commit comments