40
40
#define PARAM_STATUS "Status"
41
41
42
42
typedef enum {
43
- STATUS_NOT_STARTED = 0 ,
43
+ STATUS_NOT_STARTED = 0 , // Index in the array, not the actual status code
44
44
STATUS_RUNNING ,
45
+ STATUS_DOCKERD_STOPPED ,
46
+ STATUS_DOCKERD_RUNTIME_ERROR ,
45
47
STATUS_TLS_CERT_MISSING ,
46
48
STATUS_NO_SOCKET ,
47
49
STATUS_NO_SD_CARD ,
@@ -53,12 +55,14 @@ typedef enum {
53
55
54
56
static const char * const status_code_strs [STATUS_CODE_COUNT ] = {"-1 NOT STARTED" ,
55
57
"0 RUNNING" ,
56
- "1 TLS CERT MISSING" ,
57
- "2 NO SOCKET" ,
58
- "3 NO SD CARD" ,
59
- "4 SD CARD WRONG FS" ,
60
- "5 SD CARD WRONG PERMISSION" ,
61
- "6 SD CARD MIGRATION FAILED" };
58
+ "1 DOCKERD STOPPED" ,
59
+ "2 DOCKERD RUNTIME ERROR" ,
60
+ "3 TLS CERT MISSING" ,
61
+ "4 NO SOCKET" ,
62
+ "5 NO SD CARD" ,
63
+ "6 SD CARD WRONG FS" ,
64
+ "7 SD CARD WRONG PERMISSION" ,
65
+ "8 SD CARD MIGRATION FAILED" };
62
66
63
67
struct settings {
64
68
char * data_root ;
@@ -68,10 +72,18 @@ struct settings {
68
72
};
69
73
70
74
struct app_state {
75
+ bool allow_dockerd_to_start ;
71
76
char * sd_card_area ;
72
77
AXParameter * param_handle ;
73
78
};
74
79
80
+ // If process exited by a signal, code will be -1.
81
+ // If process exited with an exit code, signal will be 0.
82
+ struct exit_cause {
83
+ int code ;
84
+ int signal ;
85
+ };
86
+
75
87
/**
76
88
* @brief Callback called when the dockerd process exits.
77
89
*/
@@ -653,22 +665,43 @@ static void stop_dockerd(void) {
653
665
log_info ("Stopped dockerd." );
654
666
}
655
667
668
+ static struct exit_cause child_process_exit_cause (int status , GError * error ) {
669
+ struct exit_cause result ;
670
+ result .code = -1 ;
671
+ result .signal = 0 ;
672
+
673
+ if (g_spawn_check_wait_status (status , & error ) || error -> domain == G_SPAWN_EXIT_ERROR )
674
+ result .code = error ? error -> code : 0 ;
675
+ else if (error -> domain == G_SPAWN_ERROR && error -> code == G_SPAWN_ERROR_FAILED )
676
+ result .signal = status ;
677
+
678
+ return result ;
679
+ }
680
+
656
681
static void log_child_process_exit_cause (const char * name , GPid pid , int status ) {
657
682
GError * error = NULL ;
683
+ struct exit_cause exit_cause = child_process_exit_cause (status , error );
684
+
658
685
char msg [128 ];
659
686
const char * end = msg + sizeof (msg );
660
687
char * ptr = msg + g_snprintf (msg , end - msg , "Child process %s (%d)" , name , pid );
661
-
662
- if (g_spawn_check_wait_status (status , & error ) || error -> domain == G_SPAWN_EXIT_ERROR )
663
- g_snprintf (ptr , end - ptr , " exited with exit code %d" , error ? error -> code : 0 );
664
- else if (error -> domain == G_SPAWN_ERROR && error -> code == G_SPAWN_ERROR_FAILED )
665
- g_snprintf (ptr , end - ptr , " was killed by signal %d" , status );
688
+ if (exit_cause .code >= 0 )
689
+ g_snprintf (ptr , end - ptr , " exited with exit code %d" , exit_cause .code );
690
+ else if (exit_cause .signal > 0 )
691
+ g_snprintf (ptr , end - ptr , " was killed by signal %d" , exit_cause .signal );
666
692
else
667
693
g_snprintf (ptr , end - ptr , " terminated in an unexpected way: %s" , error -> message );
668
694
g_clear_error (& error );
669
695
log_debug ("%s" , msg );
670
696
}
671
697
698
+ static bool child_process_exited_with_error (int status ) {
699
+ GError * error = NULL ;
700
+ struct exit_cause exit_cause = child_process_exit_cause (status , error );
701
+ g_clear_error (& error );
702
+ return exit_cause .code > 0 ;
703
+ }
704
+
672
705
/**
673
706
* @brief Callback called when the dockerd process exits.
674
707
*/
@@ -677,6 +710,11 @@ static void dockerd_process_exited_callback(GPid pid, gint status, gpointer app_
677
710
678
711
struct app_state * app_state = app_state_void_ptr ;
679
712
713
+ bool runtime_error = child_process_exited_with_error (status );
714
+ app_state -> allow_dockerd_to_start = !runtime_error ;
715
+ status_code_t s = runtime_error ? STATUS_DOCKERD_RUNTIME_ERROR : STATUS_DOCKERD_STOPPED ;
716
+ set_status_parameter (app_state -> param_handle , s );
717
+
680
718
dockerd_process_pid = -1 ;
681
719
g_spawn_close_pid (pid );
682
720
@@ -700,26 +738,26 @@ static gboolean quit_main_loop(void*) {
700
738
* @param name Name of the updated parameter.
701
739
* @param value Value of the updated parameter.
702
740
*/
703
- static void parameter_changed_callback (const gchar * name ,
704
- const gchar * value ,
705
- __attribute__((unused )) gpointer data ) {
706
- log_debug ("Parameter %s changed to %s" , name , value );
741
+ static void
742
+ parameter_changed_callback (const gchar * name , const gchar * value , gpointer app_state_void_ptr ) {
707
743
const gchar * parname = name += strlen ("root." APP_NAME "." );
708
744
709
- for (size_t i = 0 ; i < sizeof (ax_parameters ) / sizeof (ax_parameters [0 ]); ++ i ) {
710
- if (strcmp (parname , ax_parameters [i ]) == 0 ) {
711
- log_info ("%s changed to: %s" , ax_parameters [i ], value );
712
- // Trigger a restart of dockerd from main(), but delay it 1 second.
713
- // When there are multiple AXParameter callbacks in a queue, such as
714
- // during the first parameter change after installation, any parameter
715
- // usage, even outside a callback, will cause a 20 second deadlock per
716
- // queued callback.
717
- g_timeout_add_seconds (1 , quit_main_loop , NULL );
718
- }
719
- }
745
+ log_info ("%s changed to %s" , parname , value );
746
+
747
+ struct app_state * app_state = app_state_void_ptr ;
748
+
749
+ // If dockerd has failed before, this parameter change may have resolved the problem.
750
+ app_state -> allow_dockerd_to_start = true;
751
+
752
+ // Trigger a restart of dockerd from main(), but delay it 1 second.
753
+ // When there are multiple AXParameter callbacks in a queue, such as
754
+ // during the first parameter change after installation, any parameter
755
+ // usage, even outside a callback, will cause a 20 second deadlock per
756
+ // queued callback.
757
+ g_timeout_add_seconds (1 , quit_main_loop , NULL );
720
758
}
721
759
722
- static AXParameter * setup_axparameter (void ) {
760
+ static AXParameter * setup_axparameter (struct app_state * app_state ) {
723
761
bool success = false;
724
762
GError * error = NULL ;
725
763
AXParameter * ax_parameter = ax_parameter_new (APP_NAME , & error );
@@ -733,7 +771,7 @@ static AXParameter* setup_axparameter(void) {
733
771
gboolean geresult = ax_parameter_register_callback (ax_parameter ,
734
772
parameter_path ,
735
773
parameter_changed_callback ,
736
- NULL ,
774
+ app_state ,
737
775
& error );
738
776
free (parameter_path );
739
777
@@ -784,7 +822,9 @@ int main(int argc, char** argv) {
784
822
parse_command_line (argc , argv , & log_settings );
785
823
log_init (& log_settings );
786
824
787
- app_state .param_handle = setup_axparameter ();
825
+ app_state .allow_dockerd_to_start = true;
826
+
827
+ app_state .param_handle = setup_axparameter (& app_state );
788
828
if (!app_state .param_handle ) {
789
829
log_error ("Error in setup_axparameter" );
790
830
return EX_SOFTWARE ;
@@ -797,17 +837,15 @@ int main(int argc, char** argv) {
797
837
struct sd_disk_storage * sd_disk_storage = sd_disk_storage_init (sd_card_callback , & app_state );
798
838
799
839
while (application_exit_code == EX_KEEP_RUNNING ) {
800
- if (dockerd_process_pid == -1 )
840
+ if (dockerd_process_pid == -1 && app_state . allow_dockerd_to_start )
801
841
read_settings_and_start_dockerd (& app_state );
802
842
803
843
main_loop_run ();
804
844
805
845
log_settings .debug = is_app_log_level_debug (app_state .param_handle );
806
846
807
847
stop_dockerd ();
808
- set_status_parameter (app_state .param_handle , STATUS_NOT_STARTED );
809
848
}
810
-
811
849
main_loop_unref ();
812
850
813
851
if (app_state .param_handle != NULL ) {
@@ -821,5 +859,7 @@ int main(int argc, char** argv) {
821
859
822
860
sd_disk_storage_free (sd_disk_storage );
823
861
free (app_state .sd_card_area );
862
+
863
+ set_status_parameter (app_state .param_handle , STATUS_NOT_STARTED );
824
864
return application_exit_code ;
825
865
}
0 commit comments