@@ -174,8 +174,6 @@ DECLARE_SIGNAL_HANDLER(trap_handler)
174
174
#error "CONTEXT_SP is required if HAS_STACK_OVERFLOW_DETECTION is defined"
175
175
#endif
176
176
177
- static char sig_alt_stack [SIGSTKSZ ];
178
-
179
177
/* Code compiled with ocamlopt never accesses more than
180
178
EXTRA_STACK bytes below the stack pointer. */
181
179
#define EXTRA_STACK 256
@@ -245,6 +243,10 @@ DECLARE_SIGNAL_HANDLER(segv_handler)
245
243
246
244
/* Initialization of signal stuff */
247
245
246
+ #ifdef HAS_STACK_OVERFLOW_DETECTION
247
+ static int setup_stack_overflow_detection (void );
248
+ #endif
249
+
248
250
void caml_init_signals (void )
249
251
{
250
252
/* Bound-check trap handling */
@@ -269,28 +271,91 @@ void caml_init_signals(void)
269
271
#endif
270
272
271
273
#ifdef HAS_STACK_OVERFLOW_DETECTION
272
- {
273
- stack_t stk ;
274
+ if (setup_stack_overflow_detection () != -1 ) {
274
275
struct sigaction act ;
275
- stk .ss_sp = sig_alt_stack ;
276
- stk .ss_size = SIGSTKSZ ;
277
- stk .ss_flags = 0 ;
278
276
SET_SIGACT (act , segv_handler );
279
277
act .sa_flags |= SA_ONSTACK | SA_NODEFER ;
280
278
sigemptyset (& act .sa_mask );
281
- if ( sigaltstack ( & stk , NULL ) == 0 ) { sigaction (SIGSEGV , & act , NULL ); }
279
+ sigaction (SIGSEGV , & act , NULL );
282
280
}
283
281
#endif
284
282
}
285
283
286
- CAMLexport void caml_setup_stack_overflow_detection (void )
284
+ /* Termination of signal stuff */
285
+
286
+ #if defined(TARGET_power ) || defined(TARGET_s390x ) \
287
+ || defined(HAS_STACK_OVERFLOW_DETECTION )
288
+ static void set_signal_default (int signum )
287
289
{
290
+ struct sigaction act ;
291
+ sigemptyset (& act .sa_mask );
292
+ act .sa_handler = SIG_DFL ;
293
+ act .sa_flags = 0 ;
294
+ sigaction (signum , & act , NULL );
295
+ }
296
+ #endif
297
+
298
+ int caml_stop_stack_overflow_detection (void );
299
+
300
+ void caml_terminate_signals (void )
301
+ {
302
+ #if defined(TARGET_power )
303
+ set_signal_default (SIGTRAP );
304
+ #endif
305
+
306
+ #if defined(TARGET_s390x )
307
+ set_signal_default (SIGFPE );
308
+ #endif
309
+
288
310
#ifdef HAS_STACK_OVERFLOW_DETECTION
311
+ set_signal_default (SIGSEGV );
312
+ caml_stop_stack_overflow_detection ();
313
+ #endif
314
+ }
315
+
316
+ /* Allocate and select an alternate stack for handling signals,
317
+ especially SIGSEGV signals.
318
+ Each thread needs its own alternate stack.
319
+ The alternate stack used to be statically-allocated for the main thread,
320
+ but this is incompatible with Glibc 2.34 and newer, where SIGSTKSZ
321
+ may not be a compile-time constant (issue #10250). */
322
+
323
+ #ifdef HAS_STACK_OVERFLOW_DETECTION
324
+ static int setup_stack_overflow_detection (void )
325
+ {
289
326
stack_t stk ;
290
327
stk .ss_sp = malloc (SIGSTKSZ );
328
+ if (stk .ss_sp == NULL ) return -1 ;
291
329
stk .ss_size = SIGSTKSZ ;
292
330
stk .ss_flags = 0 ;
293
- if (stk .ss_sp )
294
- sigaltstack (& stk , NULL );
331
+ if (sigaltstack (& stk , NULL ) == -1 ) {
332
+ free (stk .ss_sp );
333
+ return -1 ;
334
+ }
335
+ /* Success (or stack overflow detection not available) */
336
+ return 0 ;
337
+ }
338
+ #endif
339
+
340
+ CAMLexport void caml_setup_stack_overflow_detection (void )
341
+ {
342
+ #ifdef HAS_STACK_OVERFLOW_DETECTION
343
+ setup_stack_overflow_detection ();
344
+ #endif
345
+ }
346
+
347
+ CAMLexport int caml_stop_stack_overflow_detection (void )
348
+ {
349
+ #ifdef HAS_STACK_OVERFLOW_DETECTION
350
+ stack_t oldstk , stk ;
351
+ stk .ss_flags = SS_DISABLE ;
352
+ if (sigaltstack (& stk , & oldstk ) == -1 ) return -1 ;
353
+ /* If caml_setup_stack_overflow_detection failed, we are not using
354
+ an alternate signal stack. SS_DISABLE will be set in oldstk,
355
+ and there is nothing to free in this case. */
356
+ if (! (oldstk .ss_flags & SS_DISABLE )) free (oldstk .ss_sp );
357
+ return 0 ;
358
+ #else
359
+ return 0 ;
295
360
#endif
296
361
}
0 commit comments