return status;
}
- for (;;) {
+ for (; main.thread->enabled; ) {
actions = &main.setting->entry.items.array[cache->ats.array[at_i]].actions;
}
} // for
+ if (!main.thread->enabled) {
+ return F_signal;
+ }
+
// if ready was never found in the entry, then default to always ready.
if (main.setting->ready == controller_setting_ready_no) {
main.setting->ready = controller_setting_ready_yes;
}
}
- for (;;) {
+ for (; main.thread->enabled; ) {
entry_actions = &main.setting->entry.items.array[cache->ats.array[at_i]].actions;
break;
}
else if (entry_action->type == controller_entry_action_type_consider || entry_action->type == controller_entry_action_type_rule) {
- f_thread_lock_write(&main.thread->lock.rule);
+
+ status = controller_lock_write(main.thread, &main.thread->lock.rule);
+
+ if (status == F_signal) {
+ break;
+ }
+
+ if (!main.thread->enabled) {
+ f_thread_unlock(&main.thread->lock.rule);
+
+ break;
+ }
status = controller_rules_increase(&main.setting->rules);
}
}
+ if (!main.thread->enabled) break;
+
// the rule is not yet loaded, ensure that it is loaded.
if (status != F_true) {
memcpy(cache_name_item, cache->action.name_item.string, cache->action.name_item.used);
memcpy(cache_name_file, cache->action.name_file.string, cache->action.name_file.used);
- f_thread_lock_write(&main.thread->lock.rule);
+ status = controller_lock_write(main.thread, &main.thread->lock.rule);
+
+ if (status == F_signal) {
+ break;
+ }
+
+ if (!main.thread->enabled) {
+ f_thread_unlock(&main.thread->lock.rule);
+
+ break;
+ }
status = controller_rule_read(alias_rule, main, cache, &main.setting->rules.array[main.setting->rules.used]);
cache->action.line_action = cache_line_action;
cache->action.line_item = cache_line_item;
+ if (!main.thread->enabled) {
+ f_thread_unlock(&main.thread->lock.rule);
+
+ break;
+ }
+
if (F_status_is_error(status)) {
if (main.data->error.verbosity != f_console_verbosity_quiet) {
if (controller_find_process(alias_rule, main.thread->processs, 0) == F_false) {
f_thread_unlock(&main.thread->lock.process);
- f_thread_lock_write(&main.thread->lock.process);
+
+ status = controller_lock_write(main.thread, &main.thread->lock.process);
+
+ if (status == F_signal) {
+ break;
+ }
+
+ if (!main.thread->enabled) {
+ f_thread_unlock(&main.thread->lock.process);
+
+ break;
+ }
status = controller_processs_increase(&main.thread->processs);
// only copy the rule alias, as that is all that is needed at this point (the entire rule gets copied prior to executing/processing).
controller_process_t *process = main.thread->processs.array[main.thread->processs.used];
- f_thread_lock_write(&process->lock);
+ status = controller_lock_write(main.thread, &process->lock);
+
+ if (status == F_signal) {
+ f_thread_unlock(&main.thread->lock.process);
+
+ break;
+ }
+
+ if (!main.thread->enabled) {
+ f_thread_unlock(&process->lock);
+ f_thread_unlock(&main.thread->lock.process);
+
+ break;
+ }
process->rule.alias.used = 0;
status = controller_rule_process_begin(process_options, alias_rule, controller_rule_action_type_start, rule_options, stack, main, *cache);
- if (F_status_set_fine(status) == F_memory_not || status == F_child || status == F_signal) {
+ if (F_status_set_fine(status) == F_memory_not || status == F_child || status == F_signal || !main.thread->enabled) {
break;
}
}
}
} // for
+ if (!main.thread->enabled) {
+ return F_signal;
+ }
+
if (status == F_child || status == F_signal) {
return status;
}
return status;
}
- for (i = 0; i < process->rule.items.used; ++i) {
-
- if (!main.thread->enabled) {
- status = F_signal;
- break;
- }
+ for (i = 0; i < process->rule.items.used && main.thread->enabled; ++i) {
if (process->rule.items.array[i].type == controller_rule_item_type_setting) continue;
status = controller_rule_execute_foreground(process->rule.items.array[i].type, process->rule.items.array[i].actions.array[j], 0, process->rule.items.array[i].actions.array[j].parameters, options, main, &execute_set, process);
- if (status == F_child) break;
+ if (status == F_child || status == F_signal) break;
if (F_status_is_error(status)) {
process->rule.items.array[i].actions.array[j].status = F_status_set_error(F_failure);
status = controller_rule_execute_foreground(process->rule.items.array[i].type, process->rule.items.array[i].actions.array[j], process->rule.script.used ? process->rule.script.string : controller_default_program_script, arguments_none, options, main, &execute_set, process);
- if (status == F_child) break;
+ if (status == F_child || status == F_signal) break;
if (F_status_is_error(status)) {
process->rule.items.array[i].actions.array[j].status = F_status_set_error(F_failure);
status = controller_rule_execute_pid_with(process->rule.items.array[i].type, process->rule.items.array[i].actions.array[j], 0, process->rule.items.array[i].actions.array[j].parameters, options, main, &execute_set, process);
- if (status == F_child) break;
+ if (status == F_child || status == F_signal) break;
if (F_status_is_error(status)) {
process->rule.items.array[i].actions.array[j].status = F_status_set_error(F_failure);
f_macro_string_maps_t_delete_simple(environment);
+ if (!main.thread->enabled) {
+ return F_signal;
+ }
+
if (status == F_child || status == F_signal || F_status_is_error(status)) {
return status;
}
result = 0;
f_thread_unlock(&process->lock);
- f_thread_lock_write(&process->lock);
+
+ status = controller_lock_write(main.thread, &process->lock);
+
+ if (status == F_signal) {
+ return status;
+ }
+
+ if (!main.thread->enabled) {
+ f_thread_unlock(&process->lock);
+
+ return F_signal;
+ }
// assign the child process id to allow for the cancel process to send appropriate termination signals to the child process.
process->child = id_child;
// have the parent wait for the child process to finish.
waitpid(id_child, &result, 0);
+ if (!main.thread->enabled) {
+ f_thread_unlock(&process->lock);
+
+ return F_signal;
+ }
+
f_thread_unlock(&process->lock);
- f_thread_lock_write(&process->lock);
+
+ status = controller_lock_write(main.thread, &process->lock);
+
+ if (status == F_signal) {
+ return status;
+ }
+
+ if (!main.thread->enabled) {
+ f_thread_unlock(&process->lock);
+
+ return F_signal;
+ }
// remove the pid now that waidpid() has returned.
process->child = 0;
result = 0;
f_thread_unlock(&process->lock);
- f_thread_lock_write(&process->lock);
+
+ status = controller_lock_write(main.thread, &process->lock);
+
+ if (status == F_signal) {
+ return status;
+ }
+
+ if (!main.thread->enabled) {
+ f_thread_unlock(&process->lock);
+
+ return F_signal;
+ }
// assign the child process id to allow for the cancel process to send appropriate termination signals to the child process.
process->child = id_process;
// have the parent wait for the child process to finish. @todo do not wait, this is a background execution!
waitpid(id_process, &result, 0);
+ if (!main.thread->enabled) {
+ f_thread_unlock(&process->lock);
+
+ return F_signal;
+ }
+
f_thread_unlock(&process->lock);
- f_thread_lock_write(&process->lock);
+
+ status = controller_lock_write(main.thread, &process->lock);
+
+ if (status == F_signal) {
+ return status;
+ }
+
+ if (!main.thread->enabled) {
+ f_thread_unlock(&process->lock);
+
+ return F_signal;
+ }
// remove the pid now that waidpid() has returned. @todo do not clear until forked execution is known to have exited, this is a background execution
process->child = 0;
else {
f_thread_unlock(&main.thread->lock.rule);
}
+
+ if (!main.thread->enabled) break;
} // for
+ if (!main.thread->enabled) break;
+
if (status == F_child || status == F_signal) break;
if (F_status_is_error(status) && !(process->options & controller_rule_option_simulate)) break;
f_array_length_t id_rule = 0;
f_thread_unlock(&process->lock);
- f_thread_lock_write(&process->lock);
+
+ status = controller_lock_write(main.thread, &process->lock);
+
+ if (status == F_signal) {
+ f_thread_lock_read(&process->lock);
+
+ return status;
+ }
+
+ if (!main.thread->enabled) {
+ f_thread_unlock(&process->lock);
+ f_thread_lock_read(&process->lock);
+
+ return F_signal;
+ }
if (F_status_is_error(status)) {
process->rule.status = controller_status_simplify_error(F_status_set_fine(status));
process->rule.status = status;
}
- f_thread_lock_write(&main.thread->lock.rule);
+ status = controller_lock_write(main.thread, &main.thread->lock.rule);
+
+ if (status == F_signal) {
+ f_thread_unlock(&process->lock);
+ f_thread_lock_read(&process->lock);
+
+ return status;
+ }
+
+ if (!main.thread->enabled) {
+ f_thread_unlock(&process->lock);
+ f_thread_unlock(&main.thread->lock.rule);
+ f_thread_lock_read(&process->lock);
+
+ return F_signal;
+ }
status = controller_rule_find(process->rule.alias, main.setting->rules, &id_rule);
process = main.thread->processs.array[at];
f_thread_lock_read(&process->active);
- f_thread_lock_write(&process->lock);
+
+ status = controller_lock_write(main.thread, &process->lock);
+
+ if (status == F_signal) {
+ f_thread_unlock(&process->active);
+
+ return status;
+ }
+
+ if (!main.thread->enabled) {
+ f_thread_unlock(&process->lock);
+ f_thread_unlock(&process->active);
+
+ return F_signal;
+ }
// once a write lock on the process is achieved, it is safe to unlock the main process read lock.
f_thread_unlock(&main.thread->lock.process);
}
f_thread_unlock(&process->lock);
- f_thread_lock_write(&process->lock);
+
+ status = controller_lock_write(main.thread, &process->lock);
+
+ if (status == F_signal) {
+ f_thread_unlock(&process->active);
+
+ return status;
+ }
+
+ if (!main.thread->enabled) {
+ f_thread_unlock(&process->lock);
+ f_thread_unlock(&process->active);
+
+ return F_signal;
+ }
process->state = controller_process_state_active;
process->action = action;
status = controller_rule_process_do(process_options, process);
if (status == F_child || status == F_signal) {
+ f_thread_unlock(&process->active);
+
return status;
}
}
#ifndef _di_controller_rule_process_do_
f_status_t controller_rule_process_do(const uint8_t options, controller_process_t *process) {
- // the process lock shall be held for the duration of this processing (aside from switching between read to/from write).
- if (options & controller_process_option_asynchronous) f_thread_lock_read(&process->active);
+ // the process and active locks shall be held for the duration of this processing (aside from switching between read to/from write).
+ if (options & controller_process_option_asynchronous) {
+ f_thread_lock_read(&process->active);
+ }
+
f_thread_lock_read(&process->lock);
controller_main_t main = controller_macro_main_t_initialize((controller_data_t *) process->main_data, (controller_setting_t *) process->main_setting, (controller_thread_t *) process->main_thread);
if (!main.thread->enabled) {
f_thread_unlock(&process->lock);
- if (options & controller_process_option_asynchronous) f_thread_unlock(&process->active);
+
+ if (options & controller_process_option_asynchronous) {
+ f_thread_unlock(&process->active);
+ }
return F_signal;
}
if (controller_rule_find(process->rule.alias, main.setting->rules, &id_rule) == F_true) {
f_thread_unlock(&process->lock);
- f_thread_lock_write(&process->lock);
+
+ status = controller_lock_write(main.thread, &process->lock);
+
+ if (status == F_signal) {
+ if (options & controller_process_option_asynchronous) {
+ f_thread_unlock(&process->active);
+ }
+
+ return status;
+ }
+
+ if (!main.thread->enabled) {
+ f_thread_unlock(&process->lock);
+
+ if (options & controller_process_option_asynchronous) {
+ f_thread_unlock(&process->active);
+ }
+
+ return F_signal;
+ }
controller_rule_delete_simple(&process->rule);
}
} // for
+ if (!main.thread->enabled) {
+ f_thread_unlock(&process->lock);
+
+ if (options & controller_process_option_asynchronous) {
+ f_thread_unlock(&process->active);
+ }
+
+ return F_signal;
+ }
+
if (F_status_is_error_not(status)) {
status = f_type_array_lengths_increase(&process->stack);
}
else {
f_thread_unlock(&process->lock);
- f_thread_lock_write(&process->lock);
+
+ status = controller_lock_write(main.thread, &process->lock);
+
+ if (status == F_signal) {
+ if (options & controller_process_option_asynchronous) {
+ f_thread_unlock(&process->active);
+ }
+
+ return status;
+ }
+
+ if (!main.thread->enabled) {
+ f_thread_unlock(&process->lock);
+
+ if (options & controller_process_option_asynchronous) {
+ f_thread_unlock(&process->active);
+ }
+
+ return F_signal;
+ }
process->stack.array[process->stack.used++] = id_rule;
if (F_status_is_error(status)) {
f_thread_unlock(&main.thread->lock.rule);
- f_thread_lock_write(&main.thread->lock.rule);
+
+ status = controller_lock_write(main.thread, &main.thread->lock.rule);
+
+ if (status == F_signal) {
+ if (options & controller_process_option_asynchronous) {
+ f_thread_unlock(&process->active);
+ }
+
+ return status;
+ }
+
+ if (!main.thread->enabled) {
+ f_thread_unlock(&main.thread->lock.rule);
+
+ if (options & controller_process_option_asynchronous) {
+ f_thread_unlock(&process->active);
+ }
+
+ return F_signal;
+ }
if (controller_rule_find(process->rule.alias, main.setting->rules, &id_rule) == F_true) {
main.setting->rules.array[id_rule].status = status;
else {
f_thread_unlock(&main.thread->lock.rule);
- status = F_status_set_error(F_found_not);
+ status = controller_lock_write(main.thread, &main.thread->lock.rule);
+
+ if (status == F_signal) {
+ if (options & controller_process_option_asynchronous) {
+ f_thread_unlock(&process->active);
+ }
+
+ return status;
+ }
- f_thread_lock_write(&main.thread->lock.rule);
+ if (!main.thread->enabled) {
+ f_thread_unlock(&main.thread->lock.rule);
+
+ if (options & controller_process_option_asynchronous) {
+ f_thread_unlock(&process->active);
+ }
+
+ return F_signal;
+ }
+
+ status = F_status_set_error(F_found_not);
if (controller_rule_find(process->rule.alias, main.setting->rules, &id_rule) == F_true) {
main.setting->rules.array[id_rule].status = status;
}
}
- if (status == F_child || status == F_signal) {
+ if (status == F_child) {
return status;
}
f_thread_unlock(&process->lock);
- f_thread_lock_write(&process->lock);
+
+ if (status == F_signal) {
+ if (options & controller_process_option_asynchronous) {
+ f_thread_unlock(&process->active);
+ }
+
+ return status;
+ }
+
+ status = controller_lock_write(main.thread, &process->lock);
+
+ if (status == F_signal) {
+ if (options & controller_process_option_asynchronous) {
+ f_thread_unlock(&process->active);
+ }
+
+ return status;
+ }
+
+ if (!main.thread->enabled) {
+ f_thread_unlock(&process->lock);
+
+ if (options & controller_process_option_asynchronous) {
+ f_thread_unlock(&process->active);
+ }
+
+ return F_signal;
+ }
if ((options & controller_process_option_execute) && (options & controller_process_option_asynchronous)) {
process->state = controller_process_state_done;
process->stack.used = used_original_stack;
f_thread_unlock(&process->lock);
- if (options & controller_process_option_asynchronous) f_thread_unlock(&process->active);
+
+ if (options & controller_process_option_asynchronous) {
+ f_thread_unlock(&process->active);
+ }
if (main.thread->enabled) {
if (options & controller_process_option_execute) {
if (!main.thread->processs.used) {
f_thread_unlock(&main.thread->lock.process);
+
return;
}
+ f_status_t status = F_none;
+
f_array_length_t i = 0;
f_array_length_t j = 0;
if (process->state == controller_process_state_done) {
f_thread_unlock(&process->lock);
- f_thread_lock_write(&process->lock);
+
+ status = controller_lock_write(main.thread, &process->lock);
+
+ if (status == F_signal) {
+ f_thread_unlock(&process->active);
+
+ break;
+ }
+
+ if (!main.thread->enabled) {
+ f_thread_unlock(&process->lock);
+ f_thread_unlock(&process->active);
+
+ break;
+ }
if (process->state == controller_process_state_done) {
f_thread_unlock(&process->active);
#ifndef _di_controller_thread_cleanup_
void * controller_thread_cleanup(void *arguments) {
+ f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
+
const controller_main_t *main = (controller_main_t *) arguments;
if (!main->thread->enabled) return 0;
const unsigned int interval = main->data->parameters[controller_parameter_test].result == f_console_result_found ? controller_thread_cleanup_interval_short : controller_thread_cleanup_interval_long;
+ f_status_t status = F_none;
+
while (main->thread->enabled) {
sleep(interval);
break;
}
- f_thread_lock_write(&process->lock);
+ status = controller_lock_write(main->thread, &process->lock);
+
+ if (status == F_signal) {
+ f_thread_unlock(&process->active);
+
+ break;
+ }
+
+ if (!main->thread->enabled) {
+ f_thread_unlock(&process->lock);
+ f_thread_unlock(&process->active);
+
+ break;
+ }
process->state = controller_process_state_idle;
process->id_thread = 0;
#ifndef _di_controller_thread_control_
void * controller_thread_control(void *arguments) {
+ f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
+
controller_main_t *main = (controller_main_t *) arguments;
if (!main->thread->enabled) return 0;
#ifndef _di_controller_thread_process_
void * controller_thread_process(void *arguments) {
+ f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
+
controller_process_t *process = (controller_process_t *) arguments;
{
nanosleep(&wait, 0);
}
- f_thread_signal(process->id_thread, F_signal_kill);
-
f_thread_join(process->id_thread, 0);
process->child = 0;
process->id_thread = 0;
}
} // for
-
- // guarantee these threads are terminated.
- if (main->thread->id_cleanup) {
- f_thread_signal(main->thread->id_cleanup, F_signal_kill);
- }
-
- if (main->thread->id_control) {
- f_thread_signal(main->thread->id_control, F_signal_kill);
- }
-
- if (main->thread->id_rule) {
- f_thread_signal(main->thread->id_rule, F_signal_kill);
- }
}
#endif // _di_controller_thread_process_cancel_
#ifndef _di_controller_thread_entry_
void * controller_thread_entry(void *arguments) {
+ f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
+
controller_main_entry_t *entry = (controller_main_entry_t *) arguments;
if (!entry->main->thread->enabled) return 0;
#ifndef _di_controller_thread_rule_
void * controller_thread_rule(void *arguments) {
+ f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
+
controller_main_t *main = (controller_main_t *) arguments;
if (!main->thread->enabled) return 0;