@@ -53,6 +53,9 @@ static esif_thread_t g_udev_thread;
53
53
static Bool g_udev_quit = ESIF_TRUE ;
54
54
static char * g_udev_target = NULL ;
55
55
56
+ /* Dedicated thread to handle SIGRTMIN timer signals */
57
+ static esif_thread_t g_sigrtmin_thread ;
58
+
56
59
#define MAX_PAYLOAD 1024 /* max message size*/
57
60
58
61
static struct sockaddr_nl sock_addr_src , sock_addr_dest ;
@@ -378,6 +381,52 @@ static void sigusr1_enable()
378
381
sigaction (SIGUSR1 , & action , NULL );
379
382
}
380
383
384
+ static void sigrtmin_block (void )
385
+ {
386
+ /* Block SIGRTMIN; other threads created from the main thread
387
+ * will inherit a copy of the signal mask.
388
+ */
389
+ sigset_t set = {0 };
390
+ sigemptyset (& set );
391
+ sigaddset (& set , SIGRTMIN );
392
+ if (pthread_sigmask (SIG_BLOCK , & set , NULL )) {
393
+ ESIF_TRACE_ERROR ("Fail to block SIGRTMIN\n" );
394
+ }
395
+ }
396
+
397
+ static void * sigrtmin_worker_thread (void * ptr )
398
+ {
399
+ sigset_t set = {0 };
400
+ siginfo_t info = {0 };
401
+ struct esif_tmrm_cb_obj * cb_object_ptr = NULL ;
402
+
403
+ UNREFERENCED_PARAMETER (ptr );
404
+ sigemptyset (& set );
405
+ sigaddset (& set , SIGRTMIN );
406
+
407
+ while (1 ) { /* This thread will be canceled/killed after esif_uf_exit() */
408
+ if (-1 == sigwaitinfo (& set , & info )) { /* sigwaitinfo is a cancellation point */
409
+ ESIF_TRACE_ERROR ("sigwaitinfo failed\n" );
410
+ continue ;
411
+ }
412
+
413
+ if (SIGRTMIN != info .si_signo ) {
414
+ ESIF_TRACE_ERROR ("Received signal is not SIGRTMIN, ignore\n" );
415
+ continue ;
416
+ }
417
+
418
+ cb_object_ptr = (struct esif_tmrm_cb_obj * ) info .si_value .sival_ptr ;
419
+ if (cb_object_ptr && cb_object_ptr -> func ) {
420
+ cb_object_ptr -> func (cb_object_ptr -> cb_handle );
421
+ cb_object_ptr -> func = NULL ;
422
+ esif_ccb_free (cb_object_ptr );
423
+ } else {
424
+ ESIF_TRACE_ERROR ("Invalid timer callback object: (obj=%p, func=%p)\n" ,
425
+ cb_object_ptr , (cb_object_ptr ? cb_object_ptr -> func : NULL ));
426
+ }
427
+ }
428
+ }
429
+
381
430
#if !defined(ESIF_ATTR_INSTANCE_LOCK )
382
431
// Instance Checking Disabled in Android for now
383
432
@@ -748,7 +797,10 @@ static int run_as_daemon(int start_with_pipe, int start_with_log, int start_in_b
748
797
exit (EXIT_SUCCESS );
749
798
}
750
799
751
- /* 3. Call setsid (if background daemon) */
800
+ /* 3. Block SIGRTMIN (will re-enable it in a dedicated thread) */
801
+ sigrtmin_block ();
802
+
803
+ /* 4. Call setsid (if background daemon) */
752
804
if (start_in_background && -1 == setsid ()) {
753
805
printf ("ESIF_UFD: setsid failed. Error #%d\n" , errno );
754
806
return ESIF_FALSE ;
@@ -760,13 +812,13 @@ static int run_as_daemon(int start_with_pipe, int start_with_log, int start_in_b
760
812
}
761
813
sigterm_enable ();
762
814
763
- /* 4 . Change to known directory. Performed in main */
764
- /* 5 . Close all file descriptors incuding stdin, stdout, stderr */
815
+ /* 5 . Change to known directory. Performed in main */
816
+ /* 6 . Close all file descriptors incuding stdin, stdout, stderr */
765
817
close (STDIN_FILENO ); /* stdin */
766
818
close (STDOUT_FILENO ); /* stdout */
767
819
close (STDERR_FILENO ); /* stderr */
768
820
769
- /* 6 . Open file descriptors 0, 1, and 2 and redirect */
821
+ /* 7 . Open file descriptors 0, 1, and 2 and redirect */
770
822
/* stdin */
771
823
if (ESIF_TRUE == start_with_log ) {
772
824
unlink (cmd_out );
@@ -796,6 +848,9 @@ static int run_as_daemon(int start_with_pipe, int start_with_log, int start_in_b
796
848
esif_ccb_thread_create (& g_thread , esif_event_worker_thread , "Daemon" );
797
849
}
798
850
851
+ /* Start the thread that handles SIGRTMIN */
852
+ esif_ccb_thread_create (& g_sigrtmin_thread , sigrtmin_worker_thread , NULL );
853
+
799
854
#ifdef ESIF_FEAT_OPT_ACTION_SYSFS
800
855
/* uevent listener */
801
856
esif_udev_start ();
@@ -893,6 +948,7 @@ static int run_as_server(FILE* input, char* command, int quit_after_command)
893
948
if (!instance_lock ()) {
894
949
return ESIF_FALSE ;
895
950
}
951
+ sigrtmin_block (); /* Block SIGRTMIN (will re-enable it in a dedicated thread) */
896
952
sigterm_enable ();
897
953
898
954
g_DataVaultStartScript = ESIF_STARTUP_SCRIPT_SERVER_MODE ;
@@ -903,6 +959,9 @@ static int run_as_server(FILE* input, char* command, int quit_after_command)
903
959
esif_ccb_sleep_msec (10 );
904
960
}
905
961
962
+ /* Start the thread that handles SIGRTMIN */
963
+ esif_ccb_thread_create (& g_sigrtmin_thread , sigrtmin_worker_thread , NULL );
964
+
906
965
#ifdef ESIF_FEAT_OPT_ACTION_SYSFS
907
966
/* uevent listener */
908
967
esif_udev_start ();
@@ -1167,6 +1226,18 @@ int main (int argc, char **argv)
1167
1226
/* Exit ESIF */
1168
1227
esif_uf_exit ();
1169
1228
1229
+ /* Stop and join the SIGRTMIN worker thread.
1230
+ * All ESIF timers should have been canceled
1231
+ * after esif_uf_exit() call, so it is safe
1232
+ * to terminate the g_sigrtmin_thread now.
1233
+ */
1234
+ #ifdef ESIF_ATTR_OS_ANDROID
1235
+ pthread_kill (g_sigrtmin_thread , SIGRTMIN );
1236
+ #else
1237
+ pthread_cancel (g_sigrtmin_thread );
1238
+ #endif
1239
+ esif_ccb_thread_join (& g_sigrtmin_thread );
1240
+
1170
1241
/* Release Instance Lock and exit*/
1171
1242
instance_unlock ();
1172
1243
esif_main_exit ();
0 commit comments