]> Kevux Git Server - fll/commitdiff
Bugfix: Functions like nanosleep() are not receiving interrupt signals and similar.
authorKevin Day <thekevinday@gmail.com>
Sun, 31 Oct 2021 04:53:13 +0000 (23:53 -0500)
committerKevin Day <thekevinday@gmail.com>
Sun, 31 Oct 2021 05:02:02 +0000 (00:02 -0500)
When the thread is created, the signals are locked out so that they can be handled within the program.
The processes thread needs to be able to receive signals.
Allow the parent thread to receive all signals.

More work may be done in the future to fine tune this.
For now, the signals are just opened up entirely unless uninterruptible is designated,
This seems to allow for the thread to be cancelled even when nanosleep() is being called.
Also pass the specific signal received that is triggering a termination.

level_3/controller/c/private-rule.c
level_3/controller/c/private-thread.c

index 89fccb6be006d91600ec08b60e4a35a2f5241c84..f71eb0f0d6f5a24257aeb1e9f09b17686e778f1a 100644 (file)
@@ -1647,14 +1647,18 @@ extern "C" {
       {
         struct timespec delay = controller_time_milliseconds(controller_thread_simulation_timeout_d);
 
-        nanosleep(&delay, 0);
+        if (nanosleep(&delay, 0) == -1) {
+          status = F_signal;
+        }
       }
 
-      const f_string_static_t simulated_program = macro_f_string_static_t_initialize(f_string_empty_s, 0);
-      const f_string_statics_t simulated_arguments = f_string_statics_t_initialize;
-      fl_execute_parameter_t simulated_parameter = macro_fl_execute_parameter_t_initialize(execute_set->parameter.option, execute_set->parameter.wait, process->rule.has & controller_rule_has_environment_d ? execute_set->parameter.environment : 0, execute_set->parameter.signals, &simulated_program);
+      if (status != F_signal) {
+        const f_string_static_t simulated_program = macro_f_string_static_t_initialize(f_string_empty_s, 0);
+        const f_string_statics_t simulated_arguments = f_string_statics_t_initialize;
+        fl_execute_parameter_t simulated_parameter = macro_fl_execute_parameter_t_initialize(execute_set->parameter.option, execute_set->parameter.wait, process->rule.has & controller_rule_has_environment_d ? execute_set->parameter.environment : 0, execute_set->parameter.signals, &simulated_program);
 
-      status = fll_execute_program(controller_default_program_script_s, simulated_arguments, &simulated_parameter, &execute_set->as, (void *) &result);
+        status = fll_execute_program(controller_default_program_script_s, simulated_arguments, &simulated_parameter, &execute_set->as, (void *) &result);
+      }
     }
     else {
       status = fll_execute_program(program, arguments, &execute_set->parameter, &execute_set->as, (void *) &result);
@@ -1899,14 +1903,18 @@ extern "C" {
       {
         struct timespec delay = controller_time_milliseconds(controller_thread_simulation_timeout_d);
 
-        nanosleep(&delay, 0);
+        if (nanosleep(&delay, 0) == -1) {
+          status = F_signal;
+        }
       }
 
-      const f_string_static_t simulated_program = macro_f_string_static_t_initialize(f_string_empty_s, 0);
-      const f_string_statics_t simulated_arguments = f_string_statics_t_initialize;
-      fl_execute_parameter_t simulated_parameter = macro_fl_execute_parameter_t_initialize(execute_set->parameter.option, execute_set->parameter.wait, process->rule.has & controller_rule_has_environment_d ? execute_set->parameter.environment : 0, execute_set->parameter.signals, &simulated_program);
+      if (status != F_signal) {
+        const f_string_static_t simulated_program = macro_f_string_static_t_initialize(f_string_empty_s, 0);
+        const f_string_statics_t simulated_arguments = f_string_statics_t_initialize;
+        fl_execute_parameter_t simulated_parameter = macro_fl_execute_parameter_t_initialize(execute_set->parameter.option, execute_set->parameter.wait, process->rule.has & controller_rule_has_environment_d ? execute_set->parameter.environment : 0, execute_set->parameter.signals, &simulated_program);
 
-      status = fll_execute_program(controller_default_program_script_s, simulated_arguments, &simulated_parameter, &execute_set->as, (void *) &result);
+        status = fll_execute_program(controller_default_program_script_s, simulated_arguments, &simulated_parameter, &execute_set->as, (void *) &result);
+      }
     }
     else {
       status = fll_execute_program(program, arguments, &execute_set->parameter, &execute_set->as, (void *) &result);
@@ -2084,7 +2092,7 @@ extern "C" {
         if (rerun_item->delay) {
           struct timespec time = controller_time_milliseconds(rerun_item->delay);
 
-          if (nanosleep(&time, 0) < 0) {
+          if (nanosleep(&time, 0) == -1) {
             return -1;
           }
 
index b59345727a47afd4e83ba0c4fe38fc86f594ea7c..10451d89b39c6e5e868fe6f3f4ef2b01c5166c51 100644 (file)
@@ -24,6 +24,7 @@ extern "C" {
 
     while (global->thread->enabled == controller_thread_enabled) {
 
+      // @todo consider switching to nanosleep() which may act better with interrupts and not require f_thread_cancel().
       sleep(interval);
 
       if (global->thread->enabled != controller_thread_enabled) break;
@@ -347,6 +348,18 @@ extern "C" {
       if (!controller_thread_is_enabled(is_normal, thread)) return;
     }
 
+    // Threads are restricted during the main thread so that the signals can be processed.
+    // This thread must regain control over the signals within its own thread scope.
+    {
+      controller_main_t *main = (controller_main_t *) process->main_data;
+      controller_setting_t *setting = (controller_setting_t *) process->main_setting;
+
+      if (setting->interruptable) {
+        f_signal_mask(SIG_UNBLOCK, &main->signal.set, 0);
+        f_signal_close(&main->signal);
+      }
+    }
+
     const f_status_t status = controller_rule_process_do(controller_process_option_asynchronous_d, process);
 
     if (status == F_child) {
@@ -432,7 +445,6 @@ extern "C" {
     pid_t pid = 0;
 
     // the sleep() function that is run inside the cleanup function must be interrupted via the f_thread_cancel().
-    // @todo consider switching to nanosleep() which may act better with interrupts and not require f_thread_cancel().
     if (global->thread->id_cleanup) {
       f_thread_cancel(global->thread->id_cleanup);
       f_thread_join(global->thread->id_cleanup, 0);
@@ -463,7 +475,7 @@ extern "C" {
       for (j = 0; j < process->childs.used; ++j) {
 
         if (process->childs.array[j] > 0) {
-          f_signal_send(F_signal_termination, process->childs.array[j]);
+          f_signal_send(global->thread->signal ? global->thread->signal : F_signal_termination, process->childs.array[j]);
         }
       } // for
 
@@ -473,7 +485,7 @@ extern "C" {
           status = controller_file_pid_read(process->path_pids.array[j], &pid);
 
           if (pid) {
-            f_signal_send(F_signal_termination, pid);
+            f_signal_send(global->thread->signal ? global->thread->signal : F_signal_termination, pid);
           }
         }
       } // for
@@ -492,6 +504,8 @@ extern "C" {
       do {
         if (!process->id_thread) break;
 
+        f_thread_signal(process->id_thread, global->thread->signal ? global->thread->signal : F_signal_termination);
+
         controller_time(0, controller_thread_exit_process_cancel_wait_d, &time);
 
         status = f_thread_join_timed(process->id_thread, time, 0);
@@ -979,7 +993,6 @@ extern "C" {
 
       if (global->setting->interruptable) {
         if (information.si_signo == F_signal_interrupt || information.si_signo == F_signal_abort || information.si_signo == F_signal_quit || information.si_signo == F_signal_termination) {
-
           global->thread->signal = information.si_signo;
 
           controller_thread_process_cancel(is_normal, controller_thread_cancel_signal, global, 0);