{
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);
{
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);
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;
}
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;
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) {
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);
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
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
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);
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);