unix/fiss

src/fsvs/handle_exit.c in master
Repositories | Summary | Log | Files | LICENSE

handle_exit.c (2458B) download


  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
 12static 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
 31void 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}