From 3188fb69706f1a8557efa882950908ed5106df15 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Sat, 30 Oct 2021 23:53:13 -0500 Subject: [PATCH] Bugfix: Functions like nanosleep() are not receiving interrupt signals and similar. 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 | 30 +++++++++++++++++++----------- level_3/controller/c/private-thread.c | 21 +++++++++++++++++---- 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/level_3/controller/c/private-rule.c b/level_3/controller/c/private-rule.c index 89fccb6..f71eb0f 100644 --- a/level_3/controller/c/private-rule.c +++ b/level_3/controller/c/private-rule.c @@ -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; } diff --git a/level_3/controller/c/private-thread.c b/level_3/controller/c/private-thread.c index b593457..10451d8 100644 --- a/level_3/controller/c/private-thread.c +++ b/level_3/controller/c/private-thread.c @@ -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); -- 1.8.3.1