handle_exit.c (2458B)
1 #include "service.h" 2 3 #include <errno.h> 4 #include <limits.h> 5 #include <stdarg.h> 6 #include <stdio.h> 7 #include <string.h> 8 #include <sys/stat.h> 9 #include <unistd.h> 10 11 12 static void do_finish(struct service* s) { 13 struct stat st; 14 15 if (fstatat(s->dir, "finish", &st, 0) != -1 && st.st_mode & S_IXUSR) { 16 if ((s->pid = fork_dup_cd_exec(s->dir, "./finish", null_fd, null_fd, null_fd)) == -1) { 17 fprint(1, "error: cannot execute ./finish: %r\n"); 18 service_update_state(s, STATE_INACTIVE); 19 } else { 20 service_update_state(s, STATE_FINISHING); 21 } 22 } else if (s->fail_count == SV_FAIL_MAX) { 23 service_update_state(s, STATE_ERROR); 24 print("%s died\n", s->name); 25 } else { 26 service_update_state(s, s->restart == S_ONCE ? STATE_DONE : STATE_INACTIVE); 27 } 28 } 29 30 31 void service_handle_exit(struct service* s, bool signaled, int return_code) { 32 struct stat st; 33 34 s->pid = 0; 35 s->stop_timeout = 0; 36 37 if (s->restart == S_ONCE) 38 s->restart = S_DOWN; 39 40 switch (s->state) { 41 case STATE_SETUP: 42 service_run(s); 43 break; 44 case STATE_ACTIVE_FOREGROUND: 45 if (signaled) { 46 s->last_exit = EXIT_SIGNALED; 47 s->return_code = return_code; 48 s->fail_count++; 49 50 print("%s killed thought signal %d\n", s->name, s->return_code); 51 } else { 52 s->last_exit = EXIT_NORMAL; 53 s->return_code = return_code; 54 if (s->return_code > 0) 55 s->fail_count++; 56 else 57 s->fail_count = 0; 58 59 print("%s exited with code %d\n", s->name, s->return_code); 60 } 61 62 do_finish(s); 63 64 break; 65 case STATE_ACTIVE_DUMMY: 66 case STATE_ACTIVE_BACKGROUND: 67 case STATE_STOPPING: 68 do_finish(s); 69 break; 70 71 case STATE_FINISHING: 72 if (s->fail_count == SV_FAIL_MAX) { 73 service_update_state(s, STATE_ERROR); 74 print("%s died\n", s->name); 75 } else { 76 service_update_state(s, s->restart == S_ONCE ? STATE_DONE : STATE_INACTIVE); 77 } 78 break; 79 case STATE_STARTING: 80 if (!signaled && return_code == 0) { 81 if (fstatat(s->dir, "stop", &st, 0) != -1 && st.st_mode & S_IXUSR) { 82 service_update_state(s, STATE_ACTIVE_BACKGROUND); 83 } else { 84 do_finish(s); 85 } 86 } else if (!signaled) { 87 s->last_exit = EXIT_NORMAL; 88 s->return_code = return_code; 89 90 do_finish(s); 91 } else { // signaled 92 s->last_exit = EXIT_SIGNALED; 93 s->return_code = return_code; 94 95 do_finish(s); 96 } 97 break; 98 99 case STATE_ERROR: 100 case STATE_INACTIVE: 101 case STATE_DONE: 102 print("unexpected error: %s died but it's inactive\n", s->name); 103 } 104 }