comparison liboctave/util/quit.cc @ 31633:d9970470108a stable

Remove several race conditions with signal handler (bug #61370). This patch removes several race conditions between the interpreter and the Ctrl-C signal handler, as described in more detail in bug #61370. * libinterp/corefcn/sighandlers.h: Make can_interrupt atomic. * libinterp/corefcn/sighandlers.cc: Make can_interrupt, signals_caught atomic, use atomic value read for signals_caught, octave_interrupt_state, change 1 to true. * liboctave/util/quit.h: Move octave_interrupt_state and octave_signal_caught to C++ only code, rewrite octave_quit() function, rewrite OCTAVE_QUIT macro to use octave_quit_c() function. * liboctave/util/quit.cc: Make octave_interrupt_state and octave_signal_caught atomic, add new wrapper function octave_quit_c(). * libinterp/corefcn/interpreter.h: Make octave_initialized atomic. * libinterp/corefcn/interpreter.cc: Make octave_initialized atomic, change 0 to false. * liboctave/util/action-container.h: New namespace "util", make m_val atomic. * liboctave/util/oct-atomic.c: Reorder preprocessor if-elif-else ladder. * liboctave/util/cmd-edit.cc: Change 0 to false.
author Reinhard Resch <r_resch@a1.net>
date Sat, 03 Dec 2022 10:36:59 -0500
parents aac27ad79be6
children 7d3467f8d713
comparison
equal deleted inserted replaced
31631:ec1f34091635 31633:d9970470108a
25 25
26 #if defined (HAVE_CONFIG_H) 26 #if defined (HAVE_CONFIG_H)
27 # include "config.h" 27 # include "config.h"
28 #endif 28 #endif
29 29
30 #include <atomic>
30 #include <cstring> 31 #include <cstring>
31 32
32 #include <ostream> 33 #include <ostream>
33 #include <sstream> 34 #include <sstream>
34 #include <new> 35 #include <new>
35 36
36 #include "quit.h" 37 #include "quit.h"
37 38
38 sig_atomic_t octave_interrupt_state = 0; 39 std::atomic<sig_atomic_t> octave_interrupt_state{0};
39 40
40 volatile sig_atomic_t octave_signal_caught = 0; 41 volatile std::atomic<bool> octave_signal_caught{false};
41 42
42 void (*octave_signal_hook) (void) = nullptr; 43 void (*octave_signal_hook) (void) = nullptr;
43 void (*octave_interrupt_hook) (void) = nullptr; 44 void (*octave_interrupt_hook) (void) = nullptr;
44 45
45 OCTAVE_BEGIN_NAMESPACE(octave) 46 OCTAVE_BEGIN_NAMESPACE(octave)
93 os << st; 94 os << st;
94 } 95 }
95 } 96 }
96 } 97 }
97 98
99 void octave_quit_c (void)
100 {
101 octave_quit ();
102 }
103
98 OCTAVE_END_NAMESPACE(octave) 104 OCTAVE_END_NAMESPACE(octave)
99 105
100 void 106 void
101 octave_handle_signal (void) 107 octave_handle_signal (void)
102 { 108 {
103 if (octave_signal_hook) 109 if (octave_signal_hook)
104 octave_signal_hook (); 110 octave_signal_hook ();
105 111
106 if (octave_interrupt_state > 0) 112 sig_atomic_t curr_interrupt_state = octave_interrupt_state.load ();
107 {
108 octave_interrupt_state = -1;
109 113
110 throw octave::interrupt_exception (); 114 while (curr_interrupt_state > 0 &&
111 } 115 ! octave_interrupt_state.compare_exchange_weak (curr_interrupt_state, -1))
116 ;
117
118 if (curr_interrupt_state > 0)
119 throw octave::interrupt_exception ();
112 } 120 }