]> Kevux Git Server - controller/commitdiff
Progress: Continue setup for granting init program the ability to handle shutdown...
authorKevin Day <Kevin@kevux.org>
Sat, 2 Aug 2025 21:04:46 +0000 (16:04 -0500)
committerKevin Day <Kevin@kevux.org>
Sat, 2 Aug 2025 21:27:09 +0000 (16:27 -0500)
Replace the `fll_program_standard_set_up()` call with a custom signal setup call (`controller_signal_set_up()`).
Both the init and controller programs might as well use the same signals.
The controller program should reap its own children too, even if it is not an init program.

Use a thread condition signal to communicate to the clean up thread to perform zombie reaping.

Add missing delete in the init program.

Make sure all condition signals have proper checking around the success/failure of the condition listener.
Make sure all condition broadcasts lock before sending the signal and unlocks after.
This too must be checked for success.

Send a reap condition signal to wake up the clean up thread before cancelling the instance.

Add custom thread names using recently added thread naming FLL functions.
This should make analysis and observation of threads at runtime far easier.

The clean up thread is now located sooner in the process so that the zombie reaping may be processed during entry operations.

This should allow for the init/controller programs to receive the signals.
The init program is not yet written to do anything with them yet.

I tested the serial test like this:
```
controller -s data/data/controller/example/miscellaneous/ serial
```
I noticed that the interrupt signal before the wait is reached causes the program to exit.
Once the wait is reached and an interrupt is then sent then the exit process is started before exiting.
I remember being uncertain how to handle this and left that logic to future decisions.
As of now I believe that the exit process should always be called on interrupt.
This should be addressed ideally along with this shutdown/reboot handle or at the very least immediately after that.

24 files changed:
data/build/stand_alone/config.h
sources/c/program/controller/controller/main.c
sources/c/program/controller/init/main.c
sources/c/program/controller/init/signal.c
sources/c/program/controller/init/signal.h
sources/c/program/controller/main/common/define.h
sources/c/program/controller/main/common/string.c
sources/c/program/controller/main/common/string.h
sources/c/program/controller/main/common/type/lock.c
sources/c/program/controller/main/common/type/lock.h
sources/c/program/controller/main/controller.h
sources/c/program/controller/main/instance/wait.c
sources/c/program/controller/main/lock.c
sources/c/program/controller/main/process.c
sources/c/program/controller/main/rule/instance.c
sources/c/program/controller/main/rule/wait.c
sources/c/program/controller/main/signal.c
sources/c/program/controller/main/signal.h
sources/c/program/controller/main/thread/cleanup.c
sources/c/program/controller/main/thread/control.c
sources/c/program/controller/main/thread/entry.c
sources/c/program/controller/main/thread/instance.c
sources/c/program/controller/main/thread/rule.c
sources/c/program/controller/main/thread/signal.c

index d7287a01211d23152f7c4f681025e94e116757ed..07cf2f5d019379f0df197adfd9d39c472860e84a 100644 (file)
 //#define _di_fll_program_signal_check_simple_
 //#define _di_fll_program_signal_d_
 //#define _di_fll_program_standard_set_down_
-//#define _di_fll_program_standard_set_up_
+#define _di_fll_program_standard_set_up_
 //#define _di_fll_program_standard_signal_handle_
 #define _di_fll_program_standard_signal_received_
 //#define _di_fll_program_standard_signal_received_wait_
index 987872db6ac08e3ee8f53ace8fdc2b3e41bf7ee8..ffc0948a82625a5c0926801e59a6b00210183f1e 100644 (file)
@@ -31,7 +31,7 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) {
 
   data.setting.flag |= controller_main_flag_interruptible_d;
 
-  fll_program_standard_set_up(&data.program);
+  controller_signal_set_up(&data);
 
   f_file_umask_get(&data.program.umask);
 
index 02650d5d6e9d2b44c9f6831e8e3178082fdb913a..9c79927cdeb219b197d6ee601c5b80d74200457c 100644 (file)
@@ -34,7 +34,7 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) {
   data.process.mode = controller_process_mode_service_e;
   data.setting.flag |= controller_main_flag_interruptible_d;
 
-  controller_init_signal_set_up(&data);
+  controller_signal_set_up(&data);
 
   f_file_umask_get(&data.program.umask);
 
@@ -46,6 +46,8 @@ int main(const int argc, const f_string_t *argv, const f_string_t *envp) {
 
   controller_process(&data);
 
+  controller_delete(&data);
+
   fll_program_standard_set_down(&data.program);
 
   if (data.setting.state.status == F_child) {
index 0ff5693f8a6d82af528e203885c62995a02b03e8..8133620e4066e8a867c8822046fe2f7dc3c5ca05 100644 (file)
@@ -4,64 +4,6 @@
 extern "C" {
 #endif
 
-#ifndef _di_controller_init_signal_set_up_
-  f_status_t controller_init_signal_set_up(controller_t * const main) {
-
-    if (!main) return F_status_set_error(F_parameter);
-
-    f_signal_set_empty(&main->program.signal.set);
-    f_signal_set_add(F_signal_abort, &main->program.signal.set);
-    f_signal_set_add(F_signal_broken_pipe, &main->program.signal.set);
-    f_signal_set_add(F_signal_child, &main->program.signal.set);
-    f_signal_set_add(F_signal_continue, &main->program.signal.set);
-    f_signal_set_add(F_signal_hangup, &main->program.signal.set);
-    f_signal_set_add(F_signal_interrupt, &main->program.signal.set);
-    f_signal_set_add(F_signal_keyboard_stop, &main->program.signal.set);
-    f_signal_set_add(F_signal_power_failure, &main->program.signal.set);
-    f_signal_set_add(F_signal_quit, &main->program.signal.set);
-    f_signal_set_add(F_signal_stop, &main->program.signal.set);
-    f_signal_set_add(F_signal_termination, &main->program.signal.set);
-    f_signal_set_add(F_signal_user_1, &main->program.signal.set);
-    f_signal_set_add(F_signal_user_2, &main->program.signal.set);
-
-    f_status_t status = f_signal_mask(SIG_BLOCK, &main->program.signal.set, 0);
-    if (F_status_is_error(status)) return status;
-
-    status = f_signal_open(&main->program.signal);
-
-    // If there is an error opening a signal descriptor, then do not handle signals.
-    if (F_status_is_error(status)) {
-      f_signal_mask(SIG_UNBLOCK, &main->program.signal.set, 0);
-      f_signal_close(&main->program.signal);
-
-      return status;
-    }
-
-    // Unblock all other signals.
-    memset(&main->program.signal.set, 0, sizeof(sigset_t));
-
-    f_signal_set_fill(&main->program.signal.set);
-    f_signal_set_delete(F_signal_abort, &main->program.signal.set);
-    f_signal_set_delete(F_signal_broken_pipe, &main->program.signal.set);
-    f_signal_set_delete(F_signal_child, &main->program.signal.set);
-    f_signal_set_delete(F_signal_continue, &main->program.signal.set);
-    f_signal_set_delete(F_signal_hangup, &main->program.signal.set);
-    f_signal_set_delete(F_signal_interrupt, &main->program.signal.set);
-    f_signal_set_delete(F_signal_keyboard_stop, &main->program.signal.set);
-    f_signal_set_delete(F_signal_power_failure, &main->program.signal.set);
-    f_signal_set_delete(F_signal_quit, &main->program.signal.set);
-    f_signal_set_delete(F_signal_stop, &main->program.signal.set);
-    f_signal_set_delete(F_signal_termination, &main->program.signal.set);
-    f_signal_set_delete(F_signal_user_1, &main->program.signal.set);
-    f_signal_set_delete(F_signal_user_2, &main->program.signal.set);
-
-    status = f_signal_mask(SIG_UNBLOCK, &main->program.signal.set, 0);
-    if (F_status_is_error(status)) return status;
-
-    return F_okay;
-  }
-#endif // _di_controller_init_signal_set_up_
-
 #ifndef _di_controller_init_signal_thread_
   void controller_init_signal_thread(controller_t * const main, const uint8_t is_normal) {
 
@@ -86,18 +28,25 @@ extern "C" {
       // Prevent thread from being interrupted and auto-cancelled.
       f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
 
-      // Reap zombie processes.
-      if (information.si_signo == F_signal_child) {
-        // @todo verify that this process id is a valid child process.
-        // @todo send F_signal_terminate first?
-        // @todo a waitpid() needs to be performed to check to see how to handle the child signal.
-        //f_signal_send(F_signal_kill, information.si_pid);
-        // @todo move this to a function and identify any pid files and clear it from the process array (see calls like: status = controller_file_pid_read(instance->path_pids.array[j], &pid););
+      // Send F_signal_reserved_35 to cleanup process to reap child processes.
+      if (information.si_signo == F_signal_child || information.si_signo == F_signal_reserved_35) {
+
+        if (f_thread_mutex_lock(&main->thread.lock.reap) == F_okay) {
+          f_thread_condition_signal_all(&main->thread.lock.reap_condition);
+          f_thread_mutex_unlock(&main->thread.lock.reap);
+        }
+
+        continue;
       }
 
       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) {
         main->thread.signal = information.si_signo;
 
+        if (f_thread_mutex_lock_try(&main->thread.lock.reap) == F_okay) {
+          f_thread_condition_signal_all(&main->thread.lock.reap_condition);
+          f_thread_mutex_unlock(&main->thread.lock.reap);
+        }
+
         controller_thread_instance_cancel(main, is_normal, controller_thread_cancel_signal_e);
 
         break;
index 02b7e8686a0e43eb524c4c377d2b83e9b09195c3..9ac91d40d7e5c24c21bb107dc88b9641028e7eee 100644 (file)
@@ -17,35 +17,6 @@ extern "C" {
 #endif
 
 /**
- * Perform standard setup with custom signals.
- *
- * This is a modified version of fll_program_standard_set_up().
- *
- * @param main
- *   The main program data.
- *
- *   Must not be NULL.
- *
- * @return
- *   F_okay on success.
- *
- *   F_parameter (with error bit) if a parameter is invalid.
- *
- *   Errors (with error bit) from: f_signal_mask().
- *   Errors (with error bit) from: f_signal_open().
- *
- * @see f_signal_mask()
- * @see f_signal_open()
- * @see f_signal_set_add()
- * @see f_signal_set_delete()
- * @see f_signal_set_empty()
- * @see f_signal_set_fill()
- */
-#ifndef _di_controller_init_signal_set_up_
-  extern f_status_t controller_init_signal_set_up(controller_t * const main);
-#endif // _di_controller_init_signal_set_up_
-
-/**
  * Thread for handling signals/interrupts for the init program.
  *
  * @param main
index 053b1a758a9352b50e981a8c5aa5069b82540445..2e69c079f5a20b12562b0767f404e5035801cb48 100644 (file)
@@ -40,9 +40,11 @@ extern "C" {
  * Controller lock defines.
  *
  * controller_lock_*_d:
+ *   - max_reap:        The maximum number of processes to reap in one loop pass (currently the type is a uint8_t).
  *   - mutex_max_retry: The maximum amount of times to retry the mutex lock before giving up.
  */
 #ifndef _di_controller_lock_d_
+  #define controller_lock_max_reap_d        100
   #define controller_lock_mutex_max_retry_d 1000000
 #endif // _di_controller_lock_d_
 
index 175010d5011c4573695809de823fff8941c77040..e7b9f95557d8d4d5e6ef47b0c83d64fba4b2a420 100644 (file)
@@ -47,6 +47,15 @@ extern "C" {
   const f_string_static_t controller_rule_wished_s = macro_f_string_static_t_initialize_1(CONTROLLER_rule_wished_s, 0, CONTROLLER_rule_wished_s_length);
 #endif // _di_controller_rule_s_
 
+#ifndef _di_controller_thread_s_
+  const f_string_static_t controller_thread_cleanup_s = macro_f_string_static_t_initialize_1(CONTROLLER_thread_cleanup_s, 0, CONTROLLER_thread_cleanup_s_length);
+  const f_string_static_t controller_thread_control_s = macro_f_string_static_t_initialize_1(CONTROLLER_thread_control_s, 0, CONTROLLER_thread_control_s_length);
+  const f_string_static_t controller_thread_entry_s = macro_f_string_static_t_initialize_1(CONTROLLER_thread_entry_s, 0, CONTROLLER_thread_entry_s_length);
+  const f_string_static_t controller_thread_instance_s = macro_f_string_static_t_initialize_1(CONTROLLER_thread_instance_s, 0, CONTROLLER_thread_instance_s_length);
+  const f_string_static_t controller_thread_rule_s = macro_f_string_static_t_initialize_1(CONTROLLER_thread_rule_s, 0, CONTROLLER_thread_rule_s_length);
+  const f_string_static_t controller_thread_signal_s = macro_f_string_static_t_initialize_1(CONTROLLER_thread_signal_s, 0, CONTROLLER_thread_signal_s_length);
+#endif // _di_controller_thread_s_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index a4b57e84372b52059286f8c781aab58d11ec3436..413c7a97e59acd9e835bc8d82c71e307606e9a29 100644 (file)
@@ -257,6 +257,32 @@ extern "C" {
   extern const f_string_static_t controller_rule_wished_s;
 #endif // _di_controller_rule_s_
 
+/**
+ * The program thread name strings.
+ */
+#ifndef _di_controller_thread_s_
+  #define CONTROLLER_thread_cleanup_s  "cleanup"
+  #define CONTROLLER_thread_control_s  "control"
+  #define CONTROLLER_thread_entry_s    "entry"
+  #define CONTROLLER_thread_instance_s "instance"
+  #define CONTROLLER_thread_rule_s     "rule"
+  #define CONTROLLER_thread_signal_s   "signal"
+
+  #define CONTROLLER_thread_cleanup_s_length  7
+  #define CONTROLLER_thread_control_s_length  7
+  #define CONTROLLER_thread_entry_s_length    5
+  #define CONTROLLER_thread_instance_s_length 8
+  #define CONTROLLER_thread_rule_s_length     4
+  #define CONTROLLER_thread_signal_s_length   6
+
+  extern const f_string_static_t controller_thread_cleanup_s;
+  extern const f_string_static_t controller_thread_control_s;
+  extern const f_string_static_t controller_thread_entry_s;
+  extern const f_string_static_t controller_thread_instance_s;
+  extern const f_string_static_t controller_thread_rule_s;
+  extern const f_string_static_t controller_thread_signal_s;
+#endif // _di_controller_thread_s_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 03c53666b4797ce5309a8a32438f5bea8013cc44..d7b45db141777a3159dde0763edf848d72e6c089 100644 (file)
@@ -12,11 +12,13 @@ extern "C" {
     f_thread_mutex_delete(&lock->alert);
     f_thread_mutex_delete(&lock->cancel);
     f_thread_mutex_delete(&lock->print);
+    f_thread_mutex_delete(&lock->reap);
 
     f_thread_lock_delete(&lock->instance);
     f_thread_lock_delete(&lock->rule);
 
     f_thread_condition_delete(&lock->alert_condition);
+    f_thread_condition_delete(&lock->reap_condition);
 
     lock->flag |= controller_lock_flag_setup_not_d;
   }
index 0f368eed26b7db4a2233ed57045bc959e50568e7..34ce5e52b8bc71d071d766571137c923f4b61677 100644 (file)
@@ -30,9 +30,11 @@ extern "C" {
  *   - alert:           The alert mutex lock for waking up on alerts.
  *   - cancel:          The cancel mutex lock for locking the cancel operation.
  *   - print:           The print mutex lock.
+ *   - reap:            The reap_condition mutex lock.
  *   - instance:        The instance r/w lock.
  *   - rule:            The Rule r/w lock.
  *   - alert_condition: The condition used to trigger alerts.
+ *   - reap_condition:  The condition used to trigger zombie reaping.
  */
 #ifndef _di_controller_lock_t_
   typedef struct {
@@ -41,11 +43,13 @@ extern "C" {
     f_thread_mutex_t alert;
     f_thread_mutex_t cancel;
     f_thread_mutex_t print;
+    f_thread_mutex_t reap;
 
     f_thread_lock_t instance;
     f_thread_lock_t rule;
 
     f_thread_condition_t alert_condition;
+    f_thread_condition_t reap_condition;
   } controller_lock_t;
 
   #define controller_lock_t_initialize { \
@@ -53,9 +57,11 @@ extern "C" {
     f_thread_mutex_t_initialize, \
     f_thread_mutex_t_initialize, \
     f_thread_mutex_t_initialize, \
+    f_thread_mutex_t_initialize, \
     f_thread_lock_t_initialize, \
     f_thread_lock_t_initialize, \
     f_thread_condition_t_initialize, \
+    f_thread_condition_t_initialize, \
   }
 #endif // _di_controller_lock_t_
 
index 272e9c84ba8331be9bd69d5711f55b874d219ec7..d02031485a27b7b3fb76274d3843ca1ddaf8eb5a 100644 (file)
 #include <program/controller/main/print/warning/rule/action.h>
 #include <program/controller/main/print/warning/rule/item.h>
 #include <program/controller/main/print/warning/rule/setting.h>
+#include <program/controller/main/signal.h>
 #include <program/controller/main/status.h>
 #include <program/controller/main/time.h>
 #include <program/controller/main/thread/cleanup.h>
index 6f031fbe7b5dfbcca4f5135aea278ba618edff1d..938a3831bffce31d664d1360c64d9e659b67709a 100644 (file)
@@ -18,24 +18,26 @@ extern "C" {
     uint8_t count = 0;
 
     do {
-      f_thread_mutex_lock(&instance->wait_lock);
+      status = f_thread_mutex_lock(&instance->wait_lock);
 
-      if (count < controller_thread_timeout_wait_1_before_d) {
-        controller_time_now(controller_thread_timeout_wait_1_seconds_d, controller_thread_timeout_wait_1_nanoseconds_d, &time);
-      }
-      else if (count < controller_thread_timeout_wait_2_before_d) {
-        controller_time_now(controller_thread_timeout_wait_2_seconds_d, controller_thread_timeout_wait_2_nanoseconds_d, &time);
-      }
-      else if (count < controller_thread_timeout_wait_3_before_d) {
-        controller_time_now(controller_thread_timeout_wait_3_seconds_d, controller_thread_timeout_wait_3_nanoseconds_d, &time);
-      }
-      else {
-        controller_time_now(controller_thread_timeout_wait_4_seconds_d, controller_thread_timeout_wait_4_nanoseconds_d, &time);
-      }
+      if (status == F_okay) {
+        if (count < controller_thread_timeout_wait_1_before_d) {
+          controller_time_now(controller_thread_timeout_wait_1_seconds_d, controller_thread_timeout_wait_1_nanoseconds_d, &time);
+        }
+        else if (count < controller_thread_timeout_wait_2_before_d) {
+          controller_time_now(controller_thread_timeout_wait_2_seconds_d, controller_thread_timeout_wait_2_nanoseconds_d, &time);
+        }
+        else if (count < controller_thread_timeout_wait_3_before_d) {
+          controller_time_now(controller_thread_timeout_wait_3_seconds_d, controller_thread_timeout_wait_3_nanoseconds_d, &time);
+        }
+        else {
+          controller_time_now(controller_thread_timeout_wait_4_seconds_d, controller_thread_timeout_wait_4_nanoseconds_d, &time);
+        }
 
-      status = f_thread_condition_wait_timed(&time, &instance->wait, &instance->wait_lock);
+        status = f_thread_condition_wait_timed(&time, &instance->wait, &instance->wait_lock);
 
-      f_thread_mutex_unlock(&instance->wait_lock);
+        f_thread_mutex_unlock(&instance->wait_lock);
+      }
 
       if (!controller_thread_is_enabled_instance(instance)) return F_status_set_error(F_interrupt);
       if (F_status_is_error(status)) break;
index 9bdaa3f1e3cc63c9a566aff268b2538b66426b54..ad15289ce1e4ad728279a761de85da19856847cb 100644 (file)
@@ -14,51 +14,56 @@ extern "C" {
 
     status = f_thread_mutex_create(0, &lock->cancel);
 
-    if (F_status_is_error(status)) {
-      f_thread_mutex_delete(&lock->alert);
-
-      return status;
-    }
+    if (F_status_is_error_not(status)) {
+      status = f_thread_mutex_create(0, &lock->print);
 
-    status = f_thread_mutex_create(0, &lock->print);
+      if (F_status_is_error_not(status)) {
+        status = f_thread_mutex_create(0, &lock->reap);
 
-    if (F_status_is_error(status)) {
-      f_thread_mutex_delete(&lock->alert);
-      f_thread_mutex_delete(&lock->cancel);
+        if (F_status_is_error_not(status)) {
+          status = f_thread_lock_create(0, &lock->instance);
 
-      return status;
-    }
+          if (F_status_is_error_not(status)) {
+            status = f_thread_lock_create(0, &lock->rule);
 
-    status = f_thread_lock_create(0, &lock->instance);
+            if (F_status_is_error_not(status)) {
+              status = f_thread_condition_create(0, &lock->alert_condition);
 
-    if (F_status_is_error(status)) {
-      f_thread_mutex_delete(&lock->alert);
-      f_thread_mutex_delete(&lock->cancel);
-      f_thread_mutex_delete(&lock->print);
+              if (F_status_is_error_not(status)) {
+                status = f_thread_condition_create(0, &lock->reap_condition);
 
-      return status;
-    }
+                if (F_status_is_error(status)) {
+                  f_thread_condition_delete(&lock->alert_condition);
+                }
+              }
 
-    status = f_thread_lock_create(0, &lock->rule);
+              if (F_status_is_error(status)) {
+                f_thread_lock_delete(&lock->rule);
+              }
+            }
 
-    if (F_status_is_error(status)) {
-      f_thread_mutex_delete(&lock->alert);
-      f_thread_mutex_delete(&lock->cancel);
-      f_thread_mutex_delete(&lock->print);
-      f_thread_lock_delete(&lock->instance);
+            if (F_status_is_error(status)) {
+              f_thread_lock_delete(&lock->instance);
+            }
+          }
 
-      return status;
-    }
+          if (F_status_is_error(status)) {
+            f_thread_mutex_delete(&lock->reap);
+          }
+        }
 
+        if (F_status_is_error(status)) {
+          f_thread_mutex_delete(&lock->print);
+        }
+      }
 
-    status = f_thread_condition_create(0, &lock->alert_condition);
+      if (F_status_is_error(status)) {
+        f_thread_mutex_delete(&lock->cancel);
+      }
+    }
 
     if (F_status_is_error(status)) {
       f_thread_mutex_delete(&lock->alert);
-      f_thread_mutex_delete(&lock->cancel);
-      f_thread_mutex_delete(&lock->print);
-      f_thread_lock_delete(&lock->instance);
-      f_thread_lock_delete(&lock->rule);
 
       return status;
     }
index 7ce4b081a9c329bc6cc39fae2d1d3205983ca2fb..cb352903e7f9dce14f3f529ee05d59f8fcaa1df3 100644 (file)
@@ -57,8 +57,18 @@ extern "C" {
     else {
       status = f_thread_create(0, &main->thread.id_signal, &controller_thread_signal_normal, (void *) main);
 
+      if (F_status_is_error_not(status)) {
+        // Start the clean up thread so that it can handle any zombie reaping.
+        if (!(main->setting.flag & controller_main_flag_validate_d) && main->process.mode == controller_process_mode_service_e) {
+          if (!main->thread.id_cleanup) {
+            status = f_thread_create(0, &main->thread.id_cleanup, &controller_thread_cleanup, (void *) main);
+          }
+        }
+      }
+
       if (F_status_is_error(status)) {
         main->thread.id_signal = 0;
+        main->thread.id_cleanup = 0;
 
         controller_print_error_status(&main->program.error, macro_controller_f(f_thread_create), status);
       }
@@ -102,13 +112,8 @@ extern "C" {
           if (F_status_is_error(status)) {
             main->thread.id_rule = 0;
           }
-          else {
-            status = f_thread_create(0, &main->thread.id_cleanup, &controller_thread_cleanup, (void *) main);
-          }
 
           if (F_status_is_error(status)) {
-            main->thread.id_cleanup = 0;
-
             controller_print_error_status(&main->program.error, macro_controller_f(f_thread_create), status);
           }
         }
index 418a15b446eea543f2090773128beaf273dd8cde..12b5f048dc7f74690029210c93a151c124d77a99 100644 (file)
@@ -534,9 +534,10 @@ extern "C" {
     if (instance->state == controller_instance_state_done_e) {
       controller_thread_join(&instance->id_thread);
 
-      f_thread_mutex_lock(&instance->wait_lock);
-      f_thread_condition_signal_all(&instance->wait);
-      f_thread_mutex_unlock(&instance->wait_lock);
+      if (f_thread_mutex_lock(&instance->wait_lock) == F_okay) {
+        f_thread_condition_signal_all(&instance->wait);
+        f_thread_mutex_unlock(&instance->wait_lock);
+      }
     }
 
     instance->id = at;
@@ -664,9 +665,10 @@ extern "C" {
         instance->state = controller_instance_state_idle_e;
       }
 
-      f_thread_mutex_lock(&instance->wait_lock);
-      f_thread_condition_signal_all(&instance->wait);
-      f_thread_mutex_unlock(&instance->wait_lock);
+      if (f_thread_mutex_lock(&instance->wait_lock) == F_okay) {
+        f_thread_condition_signal_all(&instance->wait);
+        f_thread_mutex_unlock(&instance->wait_lock);
+      }
 
       f_thread_unlock(&instance->lock);
     }
@@ -916,10 +918,11 @@ extern "C" {
     instance->state = (options_force & controller_instance_option_asynchronous_e) ? controller_instance_state_done_e : controller_instance_state_idle_e;
     instance->stack.used = used_original_stack;
 
-    // inform all things waiting that the instance has finished running.
-    f_thread_mutex_lock(&instance->wait_lock);
-    f_thread_condition_signal_all(&instance->wait);
-    f_thread_mutex_unlock(&instance->wait_lock);
+    // Inform all things waiting that the instance has finished running.
+    if (f_thread_mutex_lock(&instance->wait_lock) == F_okay) {
+      f_thread_condition_signal_all(&instance->wait);
+      f_thread_mutex_unlock(&instance->wait_lock);
+    }
 
     f_thread_unlock(&instance->lock);
 
index 314d17a38b268098afdfa89c7e7b108be2dc932e..51de49d80e5a1e0175bf1a375054b2b4a73ad318 100644 (file)
@@ -107,9 +107,10 @@ extern "C" {
 
               f_thread_unlock(&instance_list[i]->active);
 
-              f_thread_mutex_lock(&instance_list[i]->wait_lock);
-              f_thread_condition_signal_all(&instance_list[i]->wait);
-              f_thread_mutex_unlock(&instance_list[i]->wait_lock);
+              if (f_thread_mutex_lock(&instance_list[i]->wait_lock) == F_okay) {
+                f_thread_condition_signal_all(&instance_list[i]->wait);
+                f_thread_mutex_unlock(&instance_list[i]->wait_lock);
+              }
             }
 
             status_lock = controller_lock_read(is_normal, F_true, &main->thread, &instance_list[i]->active);
index f598dbdd135d16db0cf127cbc13318f21fd632de..50ef3f26cc3916bf5a9e63e62239e17960e06584 100644 (file)
@@ -12,10 +12,49 @@ extern "C" {
     f_signal_set_empty(&main->program.signal.set);
     f_signal_set_add(F_signal_abort, &main->program.signal.set);
     f_signal_set_add(F_signal_broken_pipe, &main->program.signal.set);
+    f_signal_set_add(F_signal_child, &main->program.signal.set);
+    f_signal_set_add(F_signal_continue, &main->program.signal.set);
     f_signal_set_add(F_signal_hangup, &main->program.signal.set);
     f_signal_set_add(F_signal_interrupt, &main->program.signal.set);
+    f_signal_set_add(F_signal_keyboard_stop, &main->program.signal.set);
+    f_signal_set_add(F_signal_power_failure, &main->program.signal.set);
     f_signal_set_add(F_signal_quit, &main->program.signal.set);
+    f_signal_set_add(F_signal_stop, &main->program.signal.set);
     f_signal_set_add(F_signal_termination, &main->program.signal.set);
+    f_signal_set_add(F_signal_user_1, &main->program.signal.set);
+    f_signal_set_add(F_signal_user_2, &main->program.signal.set);
+
+    // Explicitly support all free signals.
+    f_signal_set_add(F_signal_reserved_35, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_36, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_37, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_38, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_39, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_40, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_41, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_42, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_43, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_44, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_45, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_46, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_47, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_48, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_49, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_50, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_51, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_52, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_53, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_54, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_55, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_56, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_57, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_58, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_59, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_60, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_61, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_62, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_63, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_64, &main->program.signal.set);
 
     fll_program_standard_signal_received_wait(&main->program, controller_signal_check_failsafe_d);
 
@@ -25,6 +64,128 @@ extern "C" {
   }
 #endif // !defined(_di_controller_signal_handler_) && !defined(_di_thread_support_)
 
+#ifndef _di_controller_signal_set_up_
+  f_status_t controller_signal_set_up(controller_t * const main) {
+
+    if (!main) return F_status_set_error(F_parameter);
+
+    f_signal_set_empty(&main->program.signal.set);
+    f_signal_set_add(F_signal_abort, &main->program.signal.set);
+    f_signal_set_add(F_signal_broken_pipe, &main->program.signal.set);
+    f_signal_set_add(F_signal_child, &main->program.signal.set);
+    f_signal_set_add(F_signal_continue, &main->program.signal.set);
+    f_signal_set_add(F_signal_hangup, &main->program.signal.set);
+    f_signal_set_add(F_signal_interrupt, &main->program.signal.set);
+    f_signal_set_add(F_signal_keyboard_stop, &main->program.signal.set);
+    f_signal_set_add(F_signal_power_failure, &main->program.signal.set);
+    f_signal_set_add(F_signal_quit, &main->program.signal.set);
+    f_signal_set_add(F_signal_stop, &main->program.signal.set);
+    f_signal_set_add(F_signal_termination, &main->program.signal.set);
+    f_signal_set_add(F_signal_user_1, &main->program.signal.set);
+    f_signal_set_add(F_signal_user_2, &main->program.signal.set);
+
+    // Explicitly support all free signals.
+    f_signal_set_add(F_signal_reserved_35, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_36, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_37, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_38, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_39, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_40, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_41, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_42, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_43, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_44, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_45, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_46, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_47, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_48, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_49, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_50, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_51, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_52, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_53, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_54, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_55, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_56, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_57, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_58, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_59, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_60, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_61, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_62, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_63, &main->program.signal.set);
+    f_signal_set_add(F_signal_reserved_64, &main->program.signal.set);
+
+    f_status_t status = f_signal_mask(SIG_BLOCK, &main->program.signal.set, 0);
+    if (F_status_is_error(status)) return status;
+
+    status = f_signal_open(&main->program.signal);
+
+    // If there is an error opening a signal descriptor, then do not handle signals.
+    if (F_status_is_error(status)) {
+      f_signal_mask(SIG_UNBLOCK, &main->program.signal.set, 0);
+      f_signal_close(&main->program.signal);
+
+      return status;
+    }
+
+    // Unblock all other signals.
+    memset(&main->program.signal.set, 0, sizeof(sigset_t));
+
+    f_signal_set_fill(&main->program.signal.set);
+    f_signal_set_delete(F_signal_abort, &main->program.signal.set);
+    f_signal_set_delete(F_signal_broken_pipe, &main->program.signal.set);
+    f_signal_set_delete(F_signal_child, &main->program.signal.set);
+    f_signal_set_delete(F_signal_continue, &main->program.signal.set);
+    f_signal_set_delete(F_signal_hangup, &main->program.signal.set);
+    f_signal_set_delete(F_signal_interrupt, &main->program.signal.set);
+    f_signal_set_delete(F_signal_keyboard_stop, &main->program.signal.set);
+    f_signal_set_delete(F_signal_power_failure, &main->program.signal.set);
+    f_signal_set_delete(F_signal_quit, &main->program.signal.set);
+    f_signal_set_delete(F_signal_stop, &main->program.signal.set);
+    f_signal_set_delete(F_signal_termination, &main->program.signal.set);
+    f_signal_set_delete(F_signal_user_1, &main->program.signal.set);
+    f_signal_set_delete(F_signal_user_2, &main->program.signal.set);
+
+    // Explicitly support all free signals.
+    f_signal_set_delete(F_signal_reserved_35, &main->program.signal.set);
+    f_signal_set_delete(F_signal_reserved_36, &main->program.signal.set);
+    f_signal_set_delete(F_signal_reserved_37, &main->program.signal.set);
+    f_signal_set_delete(F_signal_reserved_38, &main->program.signal.set);
+    f_signal_set_delete(F_signal_reserved_39, &main->program.signal.set);
+    f_signal_set_delete(F_signal_reserved_40, &main->program.signal.set);
+    f_signal_set_delete(F_signal_reserved_41, &main->program.signal.set);
+    f_signal_set_delete(F_signal_reserved_42, &main->program.signal.set);
+    f_signal_set_delete(F_signal_reserved_43, &main->program.signal.set);
+    f_signal_set_delete(F_signal_reserved_44, &main->program.signal.set);
+    f_signal_set_delete(F_signal_reserved_45, &main->program.signal.set);
+    f_signal_set_delete(F_signal_reserved_46, &main->program.signal.set);
+    f_signal_set_delete(F_signal_reserved_47, &main->program.signal.set);
+    f_signal_set_delete(F_signal_reserved_48, &main->program.signal.set);
+    f_signal_set_delete(F_signal_reserved_49, &main->program.signal.set);
+    f_signal_set_delete(F_signal_reserved_50, &main->program.signal.set);
+    f_signal_set_delete(F_signal_reserved_51, &main->program.signal.set);
+    f_signal_set_delete(F_signal_reserved_52, &main->program.signal.set);
+    f_signal_set_delete(F_signal_reserved_53, &main->program.signal.set);
+    f_signal_set_delete(F_signal_reserved_54, &main->program.signal.set);
+    f_signal_set_delete(F_signal_reserved_55, &main->program.signal.set);
+    f_signal_set_delete(F_signal_reserved_56, &main->program.signal.set);
+    f_signal_set_delete(F_signal_reserved_57, &main->program.signal.set);
+    f_signal_set_delete(F_signal_reserved_58, &main->program.signal.set);
+    f_signal_set_delete(F_signal_reserved_59, &main->program.signal.set);
+    f_signal_set_delete(F_signal_reserved_60, &main->program.signal.set);
+    f_signal_set_delete(F_signal_reserved_61, &main->program.signal.set);
+    f_signal_set_delete(F_signal_reserved_62, &main->program.signal.set);
+    f_signal_set_delete(F_signal_reserved_63, &main->program.signal.set);
+    f_signal_set_delete(F_signal_reserved_64, &main->program.signal.set);
+
+    status = f_signal_mask(SIG_UNBLOCK, &main->program.signal.set, 0);
+    if (F_status_is_error(status)) return status;
+
+    return F_okay;
+  }
+#endif // _di_controller_signal_set_up_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index c341fe96cfdffce9ccb13626cc90810b840be374..6e159bf93d0b818f2a7efeb7d0f0843e8d03abfe 100644 (file)
@@ -50,6 +50,35 @@ extern "C" {
   extern void controller_signal_handler(controller_t * const main);
 #endif // !defined(_di_controller_signal_handler_) && !defined(_di_thread_support_)
 
+/**
+ * Perform standard setup with custom signals.
+ *
+ * This is a modified version of fll_program_standard_set_up().
+ *
+ * @param main
+ *   The main program data.
+ *
+ *   Must not be NULL.
+ *
+ * @return
+ *   F_okay on success.
+ *
+ *   F_parameter (with error bit) if a parameter is invalid.
+ *
+ *   Errors (with error bit) from: f_signal_mask().
+ *   Errors (with error bit) from: f_signal_open().
+ *
+ * @see f_signal_mask()
+ * @see f_signal_open()
+ * @see f_signal_set_add()
+ * @see f_signal_set_delete()
+ * @see f_signal_set_empty()
+ * @see f_signal_set_fill()
+ */
+#ifndef _di_controller_signal_set_up_
+  extern f_status_t controller_signal_set_up(controller_t * const main);
+#endif // _di_controller_signal_set_up_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 04f628b4ccbc0e87f3248f75f961206eef10af96..3f7c1ded4e6b2af832aa362cfecb993688575c4d 100644 (file)
@@ -10,37 +10,73 @@ extern "C" {
     if (!argument) return 0;
 
     f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
+    f_thread_name_set(f_thread_caller(), controller_thread_cleanup_s);
 
     controller_t * const main = (controller_t *) argument;
 
-    if (main->thread.enabled != controller_thread_enabled_e) return 0;
-
-    const f_time_spec_t delay = macro_f_time_spec_t_initialize_1(
-      (main->setting.flag & controller_main_flag_simulate_d)
-        ? controller_thread_cleanup_interval_short_d
-        : controller_thread_cleanup_interval_long_d,
-      0
-    );
+    f_time_spec_t delay = f_time_spec_t_initialize;
+    siginfo_t signal_data;
+    uint8_t reap_count = 0;
+    f_status_t status = F_okay;
 
     while (main->thread.enabled == controller_thread_enabled_e) {
 
-      // Allow thread to be interrupted and auto-cancelled while sleeping.
-      f_thread_cancel_state_set(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
+      controller_time_now(
+        main->setting.flag & controller_main_flag_simulate_d
+          ? controller_thread_cleanup_interval_short_d
+          : controller_thread_cleanup_interval_long_d,
+        0,
+        &delay
+      );
+
+      // Use mutex lock and conditional wait, but if that fails fall back to a regular timed wait.
+      if (f_thread_mutex_lock(&main->thread.lock.reap) == F_okay) {
+        status = f_thread_condition_wait_timed(&delay, &main->thread.lock.reap_condition, &main->thread.lock.reap);
+
+        if (F_status_is_error_not(status)) {
+          f_thread_mutex_unlock(&main->thread.lock.reap);
+        }
+      }
+      else {
+        status = F_okay;
+
+        // Allow thread to be interrupted and auto-cancelled while sleeping.
+        f_thread_cancel_state_set(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
 
-      f_time_sleep_spec(delay, 0);
+        f_time_sleep_spec(delay, 0);
 
-      // Prevent thread from being interrupted and auto-cancelled.
-      f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
+        // Prevent thread from being interrupted and auto-cancelled.
+        f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
+      }
 
-      if (main->thread.enabled != controller_thread_enabled_e) break;
+      // Reaping child processes is not critical, so don't care if the reap flag cannot be unset.
+      if (!main->thread.signal && F_status_is_error_not(status)) {
+
+        memset((void *) &signal_data, 0, sizeof(siginfo_t));
+
+        reap_count = 0;
+        do {
+          if (!waitid(P_ALL, 0, &signal_data, WEXITED | WNOHANG)) {
+            if (signal_data.si_pid) {
+              if (++reap_count < controller_lock_max_reap_d) continue;
+            }
+          }
+
+        } while (F_false);
+      }
+
+      if (main->thread.enabled != controller_thread_enabled_e) {
+        if (main->thread.enabled == controller_thread_enabled_exit_e) continue;
+
+        break;
+      }
 
       if (f_thread_lock_write_try(&main->thread.lock.instance) == F_okay) {
-        f_status_t status = F_okay;
         controller_instance_t *instance = 0;
 
         f_number_unsigned_t i = 0;
 
-        for (; i < main->thread.instances.size && main->thread.enabled == controller_thread_enabled_e; ++i) {
+        for (status = F_okay; i < main->thread.instances.size && main->thread.enabled == controller_thread_enabled_e; ++i) {
 
           if (!main->thread.instances.array[i]) continue;
 
@@ -104,9 +140,10 @@ extern "C" {
                 instance->state = controller_instance_state_idle_e;
                 instance->id_thread = 0;
 
-                f_thread_mutex_lock(&instance->wait_lock);
-                f_thread_condition_signal_all(&instance->wait);
-                f_thread_mutex_unlock(&instance->wait_lock);
+                if (f_thread_mutex_lock(&instance->wait_lock) == F_okay) {
+                  f_thread_condition_signal_all(&instance->wait);
+                  f_thread_mutex_unlock(&instance->wait_lock);
+                }
 
                 f_thread_unlock(&instance->lock);
               }
index 0093c79ef201f0614f4afff1dfc268b48c31f05a..cd2f222a43c60eb2a7fc23250cc92d829a816f26 100644 (file)
@@ -10,6 +10,7 @@ extern "C" {
     if (!argument) return 0;
 
     f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
+    f_thread_name_set(f_thread_caller(), controller_thread_control_s);
 
     controller_t * const main = (controller_t *) argument;
 
index 9d863918094c406771469d7a79eb7aefd5e2596f..adbf53e7009aa04733d61052b6fd4c3b14918b75 100644 (file)
@@ -10,6 +10,7 @@ extern "C" {
     if (!argument) return 0;
 
     f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
+    f_thread_name_set(f_thread_caller(), controller_thread_entry_s);
 
     controller_t * const main = (controller_t *) argument;
 
@@ -112,7 +113,10 @@ extern "C" {
       // According to the manpages, pthread_exit() calls exit(0), which the value of main->program.child should be returned instead.
       if (main->program.child) exit(main->program.child);
     } else {
-      f_thread_condition_signal_all(&main->thread.lock.alert_condition);
+      if (f_thread_mutex_lock(&main->thread.lock.alert) == F_okay) {
+        f_thread_condition_signal_all(&main->thread.lock.alert_condition);
+        f_thread_mutex_unlock(&main->thread.lock.alert);
+      }
     }
 
     return 0;
@@ -215,7 +219,10 @@ extern "C" {
     else {
       controller_thread_instance_force_set_disable(main);
 
-      f_thread_condition_signal_all(&main->thread.lock.alert_condition);
+      if (f_thread_mutex_lock(&main->thread.lock.alert) == F_okay) {
+        f_thread_condition_signal_all(&main->thread.lock.alert_condition);
+        f_thread_mutex_unlock(&main->thread.lock.alert);
+      }
     }
 
     return 0;
index 98869320cfd4992294ee39844a5e8225243eec7b..fba2a57b03a5f81d4133f23dabb395f7b45098f1 100644 (file)
@@ -344,6 +344,11 @@ extern "C" {
         f_thread_create(0, &main->thread.id_signal, &controller_thread_signal_other, (void *) main);
       }
 
+      // Restart the cleanup thread to allow for reaping zombies while operating the Exit.
+      if (!main->thread.id_cleanup) {
+        f_thread_create(0, &main->thread.id_cleanup, &controller_thread_cleanup, (void *) main);
+      }
+
       f_status_t status = f_thread_create(0, &main->thread.id_entry, &controller_thread_exit, (void *) main);
 
       if (F_status_is_error(status)) {
@@ -428,6 +433,7 @@ extern "C" {
     if (!argument) return 0;
 
     f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
+    f_thread_name_set(f_thread_caller(), controller_thread_instance_s);
 
     controller_thread_instance((controller_instance_t * const) argument, F_true);
 
@@ -441,6 +447,7 @@ extern "C" {
     if (!argument) return 0;
 
     f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
+    f_thread_name_set(f_thread_caller(), controller_thread_instance_s);
 
     controller_thread_instance((controller_instance_t * const) argument, F_false);
 
index 7c54c04ffd055b9d3286f04828e648f6350fc145..4506f593ce4c3859cb0fc2c60c68a77057a3fcfc 100644 (file)
@@ -10,6 +10,7 @@ extern "C" {
     if (!argument) return 0;
 
     f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
+    f_thread_name_set(f_thread_caller(), controller_thread_rule_s);
 
     controller_t * const main = (controller_t *) argument;
 
index 7a5974115fd01b57d479b7900eb1d31cc90c31ae..7810d361c39d6397306994112c7561f555195ae8 100644 (file)
@@ -83,6 +83,7 @@ extern "C" {
   void * controller_thread_signal_normal(void * const argument) {
 
     f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
+    f_thread_name_set(f_thread_caller(), controller_thread_signal_s);
 
     if (argument && ((controller_t *) argument)->callback.process_thread_signal) {
       ((controller_t *) argument)->callback.process_thread_signal((controller_t *) argument, F_true);
@@ -96,6 +97,7 @@ extern "C" {
   void * controller_thread_signal_other(void * const argument) {
 
     f_thread_cancel_state_set(PTHREAD_CANCEL_DEFERRED, 0);
+    f_thread_name_set(f_thread_caller(), controller_thread_signal_s);
 
     if (argument && ((controller_t *) argument)->callback.process_thread_signal) {
       ((controller_t *) argument)->callback.process_thread_signal((controller_t *) argument, F_false);