diff libinterp/corefcn/sighandlers.cc @ 31846:5f0b8101234e

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 Tue, 21 Feb 2023 17:45:34 -0500
parents 21f9b34eb893
children 2e484f9f1f18
line wrap: on
line diff
--- a/libinterp/corefcn/sighandlers.cc	Mon Feb 20 18:06:54 2023 -0800
+++ b/libinterp/corefcn/sighandlers.cc	Tue Feb 21 17:45:34 2023 -0500
@@ -27,6 +27,7 @@
 #  include "config.h"
 #endif
 
+#include <atomic>
 #include <csignal>
 #include <cstdlib>
 
@@ -65,7 +66,7 @@
 int pipe_handler_error_count = 0;
 
 // TRUE means we can be interrupted.
-bool can_interrupt = false;
+std::atomic<bool> can_interrupt{false};
 
 // TRUE means we should try to enter the debugger on SIGINT.
 bool Vdebug_on_interrupt = false;
@@ -82,7 +83,7 @@
 static bool Vsigterm_dumps_octave_core = true;
 
 // List of signals we have caught since last call to signal_handler.
-static bool *signals_caught = nullptr;
+static std::atomic<bool> *signals_caught = nullptr;
 
 static void
 my_friendly_exit (int sig, bool save_vars = true)
@@ -194,10 +195,10 @@
 
   for (int sig = 0; sig < octave_num_signals (); sig++)
     {
-      if (signals_caught[sig])
+      bool expected = true;
+
+      if (signals_caught[sig].compare_exchange_strong (expected, false))
         {
-          signals_caught[sig] = false;
-
           if ((have_sigchld && sig == sigchld)
               || (have_sigcld && sig == sigcld))
             {
@@ -276,7 +277,7 @@
   // signal watcher thread so it should probably be more careful about
   // how it accesses global objects.
 
-  octave_signal_caught = 1;
+  octave_signal_caught = true;
 
   signals_caught[sig] = true;
 
@@ -296,7 +297,7 @@
 
       if (can_interrupt)
         {
-          octave_signal_caught = 1;
+          octave_signal_caught = true;
           octave_interrupt_state++;
         }
     }
@@ -365,7 +366,7 @@
 install_signal_handlers ()
 {
   if (! signals_caught)
-    signals_caught = new bool [octave_num_signals ()];
+    signals_caught = new std::atomic<bool> [octave_num_signals ()];
 
   for (int i = 0; i < octave_num_signals (); i++)
     signals_caught[i] = false;