@@ -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 (PEXCEPTION_POINTERS pointers, int code,
77
78
native_context_t *ucontext);
@@ -92,7 +93,12 @@ struct sigaction g_previous_sigbus;
92
93
struct sigaction g_previous_sigsegv;
93
94
struct sigaction g_previous_sigint;
94
95
struct sigaction g_previous_sigquit;
96
+ struct sigaction g_previous_sigterm;
95
97
98
+ // Pipe used for sending signal notifications to a helper thread
99
+ int g_signalPipe[2 ] = { 0 , 0 };
100
+
101
+ DWORD g_dwExternalSignalHandlerThreadId = 0 ;
96
102
97
103
/* public function definitions ************************************************/
98
104
@@ -179,6 +185,13 @@ void SEHCleanupSignals()
179
185
restore_signal (SIGSEGV, &g_previous_sigsegv);
180
186
restore_signal (SIGINT, &g_previous_sigint);
181
187
restore_signal (SIGQUIT, &g_previous_sigquit);
188
+
189
+ // Only restore if the signal handler thread was started and
190
+ // the previous handler was saved.
191
+ if (g_dwExternalSignalHandlerThreadId != 0 )
192
+ {
193
+ restore_signal (SIGTERM, &g_previous_sigterm);
194
+ }
182
195
}
183
196
184
197
/* internal function definitions **********************************************/
@@ -494,6 +507,60 @@ static void sigquit_handler(int code, siginfo_t *siginfo, void *context)
494
507
kill (gPID , code);
495
508
}
496
509
510
+ /* ++
511
+ Function :
512
+ HandleExternalSignal
513
+
514
+ Write to a pipe to kick off handling of the signal.
515
+
516
+ Parameters :
517
+ signalCode - code of the external signal
518
+
519
+ (no return value)
520
+ --*/
521
+ static void HandleExternalSignal (int signalCode)
522
+ {
523
+ BYTE signalCodeByte = (BYTE)signalCode;
524
+ ssize_t writtenBytes;
525
+ do
526
+ {
527
+ writtenBytes = write (g_signalPipe[1 ], &signalCodeByte, 1 );
528
+ }
529
+ while ((writtenBytes == -1 ) && (errno == EINTR));
530
+
531
+ if (writtenBytes == -1 )
532
+ {
533
+ // Fatal error
534
+ PROCAbort ();
535
+ }
536
+ }
537
+
538
+ /* ++
539
+ Function :
540
+ sigterm_handler
541
+
542
+ handle SIGTERM signal
543
+
544
+ Parameters :
545
+ POSIX signal handler parameter list ("man sigaction" for details)
546
+
547
+ (no return value)
548
+ --*/
549
+ static void sigterm_handler (int code, siginfo_t *siginfo, void *context)
550
+ {
551
+ if (PALIsInitialized ())
552
+ {
553
+ HandleExternalSignal (code);
554
+ }
555
+ else
556
+ {
557
+ if (g_previous_sigterm.sa_sigaction != NULL )
558
+ {
559
+ g_previous_sigterm.sa_sigaction (code, siginfo, context);
560
+ }
561
+ }
562
+ }
563
+
497
564
#ifdef INJECT_ACTIVATION_SIGNAL
498
565
/* ++
499
566
Function :
@@ -714,4 +781,111 @@ void restore_signal(int signal_id, struct sigaction *previousAction)
714
781
}
715
782
}
716
783
784
+ static
785
+ DWORD
786
+ PALAPI
787
+ ExternalSignalHandlerThreadRoutine (
788
+ PVOID
789
+ );
790
+
791
+ PAL_ERROR
792
+ StartExternalSignalHandlerThread (
793
+ CPalThread *pthr)
794
+ {
795
+ PAL_ERROR palError = NO_ERROR;
796
+
797
+ #ifndef DO_NOT_USE_SIGNAL_HANDLING_THREAD
798
+ HANDLE hThread;
799
+
800
+ if (pipe (g_signalPipe) != 0 )
801
+ {
802
+ palError = ERROR_CANNOT_MAKE;
803
+ goto done;
804
+ }
805
+
806
+ palError = InternalCreateThread (
807
+ pthr,
808
+ NULL ,
809
+ 0 ,
810
+ ExternalSignalHandlerThreadRoutine,
811
+ NULL ,
812
+ 0 ,
813
+ SignalHandlerThread, // Want no_suspend variant
814
+ &g_dwExternalSignalHandlerThreadId,
815
+ &hThread
816
+ );
817
+
818
+ if (palError != NO_ERROR)
819
+ {
820
+ ERROR (" Failure creating external signal handler thread (%d)\n " , palError);
821
+ goto done;
822
+ }
823
+
824
+ InternalCloseHandle (pthr, hThread);
825
+
826
+ handle_signal (SIGTERM, sigterm_handler, &g_previous_sigterm);
827
+ #endif // DO_NOT_USE_SIGNAL_HANDLING_THREAD
828
+
829
+ done:
830
+
831
+ return palError;
832
+ }
833
+
834
+ static
835
+ DWORD
836
+ PALAPI
837
+ ExternalSignalHandlerThreadRoutine (
838
+ PVOID
839
+ )
840
+ {
841
+ DWORD dwThreadId;
842
+ bool fContinue = TRUE ;
843
+ HANDLE hThread;
844
+ PAL_ERROR palError = NO_ERROR;
845
+ CPalThread *pthr = InternalGetCurrentThread ();
846
+
847
+ //
848
+ // Wait for a signal to occur
849
+ //
850
+
851
+ while (fContinue )
852
+ {
853
+ BYTE signalCode;
854
+ ssize_t bytesRead;
855
+
856
+ do
857
+ {
858
+ bytesRead = read (g_signalPipe[0 ], &signalCode, 1 );
859
+ }
860
+ while ((bytesRead == -1 ) && (errno == EINTR));
861
+
862
+ if (bytesRead == -1 )
863
+ {
864
+ // Fatal error
865
+ PROCAbort ();
866
+ }
867
+
868
+ switch (signalCode)
869
+ {
870
+ case SIGTERM:
871
+ {
872
+ SEHHandleTerminationRequest ();
873
+ }
874
+
875
+ default :
876
+ ASSERT (" Unexpected signal %d in signal thread\n " , signalCode);
877
+ PROCAbort ();
878
+ break ;
879
+ }
880
+ }
881
+
882
+ //
883
+ // Perform an immediate (non-graceful) shutdown
884
+ //
885
+
886
+ _exit (EXIT_FAILURE);
887
+
888
+ return 0 ;
889
+ }
890
+
717
891
#endif // !HAVE_MACH_EXCEPTIONS
0 commit comments