mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-01-18 02:39:44 +00:00
Add server watchdog and config reload test
This commit is contained in:
parent
c7d6ce71d5
commit
2716228074
@ -279,6 +279,7 @@ ATOM(bool_t, vomp, 0, boolean,, "")
|
||||
ATOM(bool_t, trace, 0, boolean,, "")
|
||||
ATOM(bool_t, profiling, 0, boolean,, "")
|
||||
ATOM(bool_t, linkstate, 0, boolean,, "")
|
||||
ATOM(bool_t, watchdog, 0, boolean,, "")
|
||||
END_STRUCT
|
||||
|
||||
#define LOG_FORMAT_OPTIONS \
|
||||
@ -320,10 +321,16 @@ STRUCT_DEFAULT(log_format, android)
|
||||
ATOM_DEFAULT(show_pid, 0)
|
||||
END_STRUCT_DEFAULT
|
||||
|
||||
STRUCT(watchdog)
|
||||
STRING(256, executable, "", absolute_path,, "Absolute path of watchdog executable")
|
||||
ATOM(uint32_t, interval_ms, 60000, uint32_nonzero,, "Time interval between watchdog invocations, in milliseconds")
|
||||
END_STRUCT
|
||||
|
||||
STRUCT(server)
|
||||
STRING(256, chdir, "/", absolute_path,, "Absolute path of chdir(2) for server process")
|
||||
STRING(256, interface_path, "", str_nonempty,, "Path of directory containing interface files, either absolute or relative to instance directory")
|
||||
ATOM(bool_t, respawn_on_crash, 0, boolean,, "If true, server will exec(2) itself on fatal signals, eg SEGV")
|
||||
SUB_STRUCT(watchdog, watchdog,)
|
||||
END_STRUCT
|
||||
|
||||
STRUCT(monitor)
|
||||
|
20
overlay.c
20
overlay.c
@ -112,14 +112,15 @@ int overlayServerMode()
|
||||
and smaller values would affect CPU and energy use, and make the simulation less realistic. */
|
||||
|
||||
#define SCHEDULE(X, Y, D) { \
|
||||
static struct profile_total _stats_##X={.name="" #X "",}; \
|
||||
static struct sched_ent _sched_##X={\
|
||||
.stats = &_stats_##X, \
|
||||
.function=X,\
|
||||
}; \
|
||||
_sched_##X.alarm=(gettime_ms()+Y);\
|
||||
_sched_##X.deadline=(gettime_ms()+Y+D);\
|
||||
schedule(&_sched_##X); }
|
||||
static struct profile_total _stats_##X = {.name="" #X "",}; \
|
||||
static struct sched_ent _sched_##X = { \
|
||||
.stats = &_stats_##X, \
|
||||
.function=X, \
|
||||
}; \
|
||||
_sched_##X.alarm = gettime_ms() + (Y);\
|
||||
_sched_##X.deadline = _sched_##X.alarm + (D);\
|
||||
schedule(&_sched_##X); \
|
||||
}
|
||||
|
||||
/* Periodically check for server shut down */
|
||||
SCHEDULE(server_shutdown_check, 0, 100);
|
||||
@ -154,6 +155,9 @@ schedule(&_sched_##X); }
|
||||
/* Calculate (and possibly show) CPU usage stats periodically */
|
||||
SCHEDULE(fd_periodicstats, 3000, 500);
|
||||
|
||||
/* Invoke the watchdog executable periodically */
|
||||
SCHEDULE(server_watchdog, config.server.watchdog.interval_ms, 100);
|
||||
|
||||
#undef SCHEDULE
|
||||
|
||||
// log message used by tests to wait for the server to start
|
||||
|
1
serval.h
1
serval.h
@ -233,6 +233,7 @@ int server_get_proc_state(const char *path, char *buff, size_t buff_len);
|
||||
int server_create_stopfile();
|
||||
int server_remove_stopfile();
|
||||
int server_check_stopfile();
|
||||
void server_watchdog(struct sched_ent *alarm);
|
||||
void overlay_mdp_clean_socket_files();
|
||||
void serverCleanUp();
|
||||
|
||||
|
61
server.c
61
server.c
@ -65,7 +65,6 @@ int server_pid()
|
||||
return -1;
|
||||
const char *p = strrchr(ppath, '/');
|
||||
assert(p != NULL);
|
||||
|
||||
FILE *f = fopen(ppath, "r");
|
||||
if (f == NULL) {
|
||||
if (errno != ENOENT)
|
||||
@ -226,6 +225,66 @@ void server_config_reload(struct sched_ent *alarm)
|
||||
}
|
||||
}
|
||||
|
||||
/* Called periodically by the server process in its main loop.
|
||||
*/
|
||||
void server_watchdog(struct sched_ent *alarm)
|
||||
{
|
||||
if (config.server.watchdog.executable[0]) {
|
||||
const char *argv[2];
|
||||
argv[0] = config.server.watchdog.executable;
|
||||
argv[1] = NULL;
|
||||
strbuf argv_sb = strbuf_append_argv(strbuf_alloca(1024), 1, argv);
|
||||
switch (fork()) {
|
||||
case 0: {
|
||||
/* Child, should fork() again to create orphan process. */
|
||||
pid_t watchdog_pid;
|
||||
switch (watchdog_pid = fork()) {
|
||||
case 0:
|
||||
/* Grandchild, should exec() watchdog. */
|
||||
close_log_file();
|
||||
signal(SIGTERM, SIG_DFL);
|
||||
close(0);
|
||||
close(1);
|
||||
close(2);
|
||||
execv(config.server.watchdog.executable, (char **)argv);
|
||||
// Don't use FATALF_perror() because we want to use _exit(2) not exit(2).
|
||||
LOGF_perror(LOG_LEVEL_FATAL, "execv(%s, [%s])",
|
||||
alloca_str_toprint(config.server.watchdog.executable),
|
||||
strbuf_str(argv_sb)
|
||||
);
|
||||
break;
|
||||
case -1:
|
||||
/* grandchild fork failed */
|
||||
WHY_perror("fork");
|
||||
break;
|
||||
default:
|
||||
/* Child, report grandchild's PID. */
|
||||
if (config.debug.watchdog)
|
||||
LOGF(LOG_LEVEL_DEBUG, "STARTED WATCHDOG pid=%u executable=%s argv=[%s]",
|
||||
watchdog_pid,
|
||||
alloca_str_toprint(config.server.watchdog.executable),
|
||||
strbuf_str(argv_sb)
|
||||
);
|
||||
do { _exit(0); } while (1);
|
||||
break;
|
||||
}
|
||||
do { _exit(-1); } while (1);
|
||||
break;
|
||||
}
|
||||
case -1:
|
||||
/* child fork failed */
|
||||
WHY_perror("fork");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (alarm) {
|
||||
time_ms_t now = gettime_ms();
|
||||
alarm->alarm = now + config.server.watchdog.interval_ms;
|
||||
alarm->deadline = alarm->alarm + 100;
|
||||
schedule(alarm);
|
||||
}
|
||||
}
|
||||
|
||||
/* Called periodically by the server process in its main loop.
|
||||
*/
|
||||
void server_shutdown_check(struct sched_ent *alarm)
|
||||
|
62
tests/server
62
tests/server
@ -142,4 +142,66 @@ teardown_NoZombie() {
|
||||
assert_no_servald_processes
|
||||
}
|
||||
|
||||
doc_ServerWatchdog="Server process invokes watchdog periodically"
|
||||
setup_ServerWatchdog() {
|
||||
cat >watchdog <<EOF
|
||||
#!/bin/sh
|
||||
date >> $PWD/trace
|
||||
EOF
|
||||
chmod 0550 watchdog
|
||||
>trace
|
||||
setup
|
||||
executeOk_servald config \
|
||||
set log.console.level debug \
|
||||
set log.console.show_pid true \
|
||||
set debug.watchdog on \
|
||||
set server.watchdog.executable "$PWD/watchdog" \
|
||||
set server.watchdog.interval_ms 100
|
||||
start_servald_server
|
||||
}
|
||||
test_ServerWatchdog() {
|
||||
wait_until --sleep=0.1 --timeout=15 line_count_at_least trace 10
|
||||
stop_servald_server
|
||||
assert_servald_server_no_errors
|
||||
}
|
||||
line_count_at_least() {
|
||||
local file="$1"
|
||||
local lines="$2"
|
||||
[ $(wc -l <"$file") -ge "$lines" ]
|
||||
}
|
||||
|
||||
doc_ReloadConfigAuto="Server automatically reloads configuration"
|
||||
setup_ReloadConfigAuto() {
|
||||
cat >watchdog1 <<EOF
|
||||
#!/bin/sh
|
||||
date >> $PWD/trace1
|
||||
EOF
|
||||
cat >watchdog2 <<EOF
|
||||
#!/bin/sh
|
||||
date >> $PWD/trace2
|
||||
EOF
|
||||
chmod 0550 watchdog1 watchdog2
|
||||
>trace1
|
||||
>trace2
|
||||
setup
|
||||
executeOk_servald config \
|
||||
set log.console.level debug \
|
||||
set log.console.show_time true \
|
||||
set log.console.show_pid true \
|
||||
set debug.watchdog on \
|
||||
set server.watchdog.executable "$PWD/watchdog1" \
|
||||
set server.watchdog.interval_ms 100
|
||||
start_servald_server
|
||||
}
|
||||
test_ReloadConfigAuto() {
|
||||
wait_until --sleep=0.5 --timeout=15 line_count_at_least trace1 3
|
||||
assert [ $(wc -l <trace2) -eq 0 ]
|
||||
executeOk_servald config \
|
||||
set server.watchdog.executable "$PWD/watchdog2"
|
||||
tfw_cat --stderr
|
||||
wait_until --sleep=0.5 --timeout=15 line_count_at_least trace2 3
|
||||
stop_servald_server
|
||||
assert_servald_server_no_errors
|
||||
}
|
||||
|
||||
runTests "$@"
|
||||
|
Loading…
Reference in New Issue
Block a user