@@ -38,8 +38,8 @@ Interrupt and signal handling for Cython
38
38
#if HAVE_SYS_TYPES_H
39
39
#include <sys/types.h>
40
40
#endif
41
- #if HAVE_SYS_TIME_H
42
- #include <sys/ time.h>
41
+ #if HAVE_TIME_H
42
+ #include <time.h>
43
43
#endif
44
44
#if HAVE_SYS_WAIT_H
45
45
#include <sys/wait.h>
@@ -102,7 +102,7 @@ void custom_set_pending_signal(int sig){
102
102
103
103
104
104
#if ENABLE_DEBUG_CYSIGNALS
105
- static struct timeval sigtime ; /* Time of signal */
105
+ static struct timespec sigtime ; /* Time of signal */
106
106
#endif
107
107
108
108
/* The cysigs object (there is a unique copy of this, shared by all
@@ -155,6 +155,52 @@ static inline void reset_CPU(void)
155
155
#endif
156
156
}
157
157
158
+ static inline void print_stderr (const char * s )
159
+ {
160
+ /* Using stdio (fputs, fprintf, fflush) from inside a signal
161
+ * handler is undefined, see signal-safety(7). We use write(2)
162
+ * instead, which is async-signal-safe according to POSIX. */
163
+ write (2 , s , strlen (s ));
164
+ }
165
+
166
+ /* str should have enough space allocated */
167
+ static inline void ulong_to_str (unsigned long val , char * str , int base )
168
+ {
169
+ const char xdigits [16 ] = "0123456789abcdef" ;
170
+ unsigned long aux ;
171
+ int len ;
172
+
173
+ len = 1 ; aux = val ;
174
+ while (aux /= base ) len ++ ;
175
+
176
+ str += len ; * str = 0 ;
177
+ do * -- str = xdigits [val % base ]; while (val /= base );
178
+ }
179
+
180
+ static inline void long_to_str (long val , char * str , int base )
181
+ {
182
+ if (val < 0 ) * str ++ = '-' ;
183
+ ulong_to_str (val < 0 ? - val : val , str , base );
184
+ }
185
+
186
+ static inline void print_stderr_long (long val )
187
+ {
188
+ char buf [21 ];
189
+ long_to_str (val , buf , 10 );
190
+ print_stderr (buf );
191
+ }
192
+
193
+ static inline void print_stderr_ptr (void * ptr )
194
+ {
195
+ if (!ptr )
196
+ print_stderr ("(nil)" );
197
+ else {
198
+ char buf [17 ];
199
+ ulong_to_str ((unsigned long )ptr , buf , 16 );
200
+ print_stderr ("0x" );
201
+ print_stderr (buf );
202
+ }
203
+ }
158
204
159
205
/* Reset all signal handlers and the signal mask to their defaults. */
160
206
static inline void sig_reset_defaults (void ) {
@@ -234,12 +280,16 @@ static void cysigs_interrupt_handler(int sig)
234
280
{
235
281
#if ENABLE_DEBUG_CYSIGNALS
236
282
if (cysigs .debug_level >= 1 ) {
237
- fprintf (stderr , "\n*** SIG %i *** %s sig_on\n" , sig , (cysigs .sig_on_count > 0 ) ? "inside" : "outside" );
283
+ print_stderr ("\n*** SIG " );
284
+ print_stderr_long (sig );
285
+ if (cysigs .sig_on_count > 0 )
286
+ print_stderr (" *** inside sig_on\n" );
287
+ else
288
+ print_stderr (" *** outside sig_on\n" );
238
289
if (cysigs .debug_level >= 3 ) print_backtrace ();
239
- fflush (stderr );
240
290
/* Store time of this signal, unless there is already a
241
291
* pending signal. */
242
- if (!cysigs .interrupt_received ) gettimeofday ( & sigtime , NULL );
292
+ if (!cysigs .interrupt_received ) clock_gettime ( CLOCK_MONOTONIC , & sigtime );
243
293
}
244
294
#endif
245
295
@@ -288,10 +338,11 @@ static void cysigs_signal_handler(int sig)
288
338
/* We are inside sig_on(), so we can handle the signal! */
289
339
#if ENABLE_DEBUG_CYSIGNALS
290
340
if (cysigs .debug_level >= 1 ) {
291
- fprintf (stderr , "\n*** SIG %i *** inside sig_on\n" , sig );
341
+ print_stderr ("\n*** SIG " );
342
+ print_stderr_long (sig );
343
+ print_stderr (" *** inside sig_on\n" );
292
344
if (cysigs .debug_level >= 3 ) print_backtrace ();
293
- fflush (stderr );
294
- gettimeofday (& sigtime , NULL );
345
+ clock_gettime (CLOCK_MONOTONIC , & sigtime );
295
346
}
296
347
#endif
297
348
@@ -401,15 +452,19 @@ static void setup_trampoline(void)
401
452
static void do_raise_exception (int sig )
402
453
{
403
454
#if ENABLE_DEBUG_CYSIGNALS
404
- struct timeval raisetime ;
455
+ struct timespec raisetime ;
405
456
if (cysigs .debug_level >= 2 ) {
406
- gettimeofday ( & raisetime , NULL );
407
- long delta_ms = (raisetime .tv_sec - sigtime .tv_sec )* 1000L + (( long ) raisetime .tv_usec - ( long ) sigtime .tv_usec )/ 1000 ;
457
+ clock_gettime ( CLOCK_MONOTONIC , & raisetime );
458
+ long delta_ms = (raisetime .tv_sec - sigtime .tv_sec )* 1000L + (raisetime .tv_nsec - sigtime .tv_nsec )/ 1000000L ;
408
459
PyGILState_STATE gilstate = PyGILState_Ensure ();
409
- fprintf (stderr , "do_raise_exception(sig=%i)\nPyErr_Occurred() = %p\nRaising Python exception %li ms after signal...\n" ,
410
- sig , PyErr_Occurred (), delta_ms );
460
+ print_stderr ("do_raise_exception(sig=" );
461
+ print_stderr_long (sig );
462
+ print_stderr (")\nPyErr_Occurred() = " );
463
+ print_stderr_ptr (PyErr_Occurred ());
464
+ print_stderr ("\nRaising Python exception " );
465
+ print_stderr_long (delta_ms );
466
+ print_stderr ("ms after signal...\n" );
411
467
PyGILState_Release (gilstate );
412
- fflush (stderr );
413
468
}
414
469
#endif
415
470
@@ -550,39 +605,32 @@ static void setup_cysignals_handlers(void)
550
605
551
606
static void print_sep (void )
552
607
{
553
- fputs ("------------------------------------------------------------------------\n" ,
554
- stderr );
555
- fflush (stderr );
608
+ print_stderr ("------------------------------------------------------------------------\n" );
556
609
}
557
610
558
611
/* Print a backtrace if supported by libc */
559
612
static void print_backtrace ()
560
613
{
561
- fflush (stderr );
562
614
#if HAVE_BACKTRACE
563
615
void * backtracebuffer [BACKTRACELEN ];
564
616
int btsize = backtrace (backtracebuffer , BACKTRACELEN );
565
617
if (btsize )
566
618
backtrace_symbols_fd (backtracebuffer , btsize , 2 );
567
619
else
568
- fputs ("(no backtrace available)\n" , stderr );
620
+ print_stderr ("(no backtrace available)\n" );
569
621
print_sep ();
570
622
#endif
571
623
}
572
624
573
625
/* Print a backtrace using gdb */
574
- static void print_enhanced_backtrace (void )
626
+ static inline void print_enhanced_backtrace (void )
575
627
{
576
628
/* Bypass Linux Yama restrictions on ptrace() to allow debugging */
577
629
/* See https://www.kernel.org/doc/Documentation/security/Yama.txt */
578
630
#ifdef PR_SET_PTRACER
579
631
prctl (PR_SET_PTRACER , PR_SET_PTRACER_ANY , 0 , 0 , 0 );
580
632
#endif
581
633
582
- /* Flush all buffers before forking */
583
- fflush (stdout );
584
- fflush (stderr );
585
-
586
634
/* Enhanced backtraces are only supported on POSIX systems */
587
635
#if HAVE_FORK
588
636
pid_t parent_pid = getpid ();
@@ -591,7 +639,9 @@ static void print_enhanced_backtrace(void)
591
639
if (pid < 0 )
592
640
{
593
641
/* Failed to fork: no problem, just ignore */
594
- perror ("cysignals fork" );
642
+ print_stderr ("cysignals fork: " );
643
+ print_stderr (strerror (errno ));
644
+ print_stderr ("\n" );
595
645
return ;
596
646
}
597
647
@@ -601,20 +651,21 @@ static void print_enhanced_backtrace(void)
601
651
602
652
/* We deliberately put these variables on the stack to avoid
603
653
* malloc() calls, the heap might be messed up! */
604
- char path [ 1024 ] ;
654
+ char * path = "cysignals-CSI" ;
605
655
char pid_str [32 ];
606
656
char * argv [5 ];
607
657
608
- snprintf (path , sizeof (path ), "cysignals-CSI" );
609
- snprintf (pid_str , sizeof (pid_str ), "%i" , parent_pid );
658
+ long_to_str (parent_pid , pid_str , 10 );
610
659
611
660
argv [0 ] = "cysignals-CSI" ;
612
661
argv [1 ] = "--no-color" ;
613
662
argv [2 ] = "--pid" ;
614
663
argv [3 ] = pid_str ;
615
664
argv [4 ] = NULL ;
616
665
execvp (path , argv );
617
- perror ("cysignals failed to execute cysignals-CSI" );
666
+ print_stderr ("cysignals failed to execute cysignals-CSI: " );
667
+ print_stderr (strerror (errno ));
668
+ print_stderr ("\n" );
618
669
exit (2 );
619
670
}
620
671
/* Wait for cysignals-CSI to finish */
@@ -649,17 +700,12 @@ static void sigdie(int sig, const char* s)
649
700
#endif
650
701
651
702
if (s ) {
652
- /* Using fprintf from inside a signal handler is undefined,
653
- see signal-safety(7). We use write(2) instead, which is
654
- async-signal-safe according to POSIX. */
655
- const char * message =
656
- "\n"
703
+ print_stderr (s );
704
+ print_stderr ("\n"
657
705
"This probably occurred because a *compiled* module has a bug\n"
658
706
"in it and is not properly wrapped with sig_on(), sig_off().\n"
659
- "Python will now terminate.\n"
660
- "------------------------------------------------------------------------\n" ;
661
- write (2 , s , strlen (s ));
662
- write (2 , message , strlen (message ));
707
+ "Python will now terminate.\n" );
708
+ print_sep ();
663
709
}
664
710
665
711
dienow :
0 commit comments