smartdns: support restart smartdns in docker.

This commit is contained in:
Nick Peng
2023-12-01 20:41:31 +08:00
parent 407aba08c5
commit fd2eb6980f
6 changed files with 118 additions and 34 deletions

View File

@@ -2,4 +2,4 @@
# /etc/init.d/smartdns. # /etc/init.d/smartdns.
# Options to pass to smartdns # Options to pass to smartdns
SMART_DNS_OPTS= SMART_DNS_OPTS= -R

View File

@@ -340,9 +340,12 @@ case "$1" in
exit 1 exit 1
fi fi
SMARTDNS_OPTION=""
[ "$SMARTDNS_CRASH_RESTART" = "1" ] && SMARTDNS_OPTION="$SMARTDNS_OPTION -R"
set_smartdns_port set_smartdns_port
get_tz get_tz
$SMARTDNS_BIN -c "$SMARTDNS_CONF" -p $SMARTDNS_PID $SMARTDNS_BIN -c "$SMARTDNS_CONF" -p $SMARTDNS_PID $SMARTDNS_OPTION
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
clear_rule clear_rule
exit 1 exit 1

View File

@@ -6,3 +6,6 @@ SMARTDNS_WORKMODE="1"
# smartdns port # smartdns port
SMARTDNS_PORT="535" SMARTDNS_PORT="535"
# restart when crash
SMARTDNS_CRASH_RESTART="1"

View File

@@ -55,6 +55,13 @@
#define SMARTDNS_PID_FILE "/run/smartdns.pid" #define SMARTDNS_PID_FILE "/run/smartdns.pid"
#define SMARTDNS_LEGACY_PID_FILE "/var/run/smartdns.pid" #define SMARTDNS_LEGACY_PID_FILE "/var/run/smartdns.pid"
#define TMP_BUFF_LEN_32 32 #define TMP_BUFF_LEN_32 32
#define SMARTDNS_CRASH_CODE 254
typedef enum {
SMARTDNS_RUN_MONITOR_OK = 0,
SMARTDNS_RUN_MONITOR_ERROR = 1,
SMARTDNS_RUN_MONITOR_EXIT = 2,
} smartdns_run_monitor_ret;
static int verbose_screen; static int verbose_screen;
@@ -622,7 +629,7 @@ static void _sig_error_exit(int signo, siginfo_t *siginfo, void *ct)
__DATE__, __TIME__, arch); __DATE__, __TIME__, arch);
print_stack(); print_stack();
sleep(1); sleep(1);
_exit(0); _exit(SMARTDNS_CRASH_CODE);
} }
static int sig_list[] = {SIGSEGV, SIGABRT, SIGBUS, SIGILL, SIGFPE}; static int sig_list[] = {SIGSEGV, SIGABRT, SIGBUS, SIGILL, SIGFPE};
@@ -732,14 +739,22 @@ static void _smartdns_early_log(struct tlog_loginfo *loginfo, const char *format
{ {
char log_buf[TLOG_MAX_LINE_LEN]; char log_buf[TLOG_MAX_LINE_LEN];
int sys_log_level = LOG_INFO; int sys_log_level = LOG_INFO;
int log_buf_maxlen = 0;
if (loginfo->level < TLOG_WARN) { if (loginfo->level < TLOG_WARN) {
return; return;
} }
int len = vsnprintf(log_buf, sizeof(log_buf), format, ap); log_buf_maxlen = sizeof(log_buf) - 2;
log_buf[log_buf_maxlen] = '\0';
int len = vsnprintf(log_buf, log_buf_maxlen, format, ap);
if (len <= 0) { if (len <= 0) {
return; return;
} else if (len >= log_buf_maxlen) {
log_buf[log_buf_maxlen - 2] = '.';
log_buf[log_buf_maxlen - 3] = '.';
log_buf[log_buf_maxlen - 4] = '.';
len = log_buf_maxlen - 1;
} }
if (log_buf[len - 1] != '\n') { if (log_buf[len - 1] != '\n') {
@@ -747,6 +762,8 @@ static void _smartdns_early_log(struct tlog_loginfo *loginfo, const char *format
len++; len++;
} }
log_buf[len] = '\0';
fprintf(stderr, "%s", log_buf); fprintf(stderr, "%s", log_buf);
switch (loginfo->level) { switch (loginfo->level) {
@@ -774,45 +791,93 @@ static void _smartdns_early_log(struct tlog_loginfo *loginfo, const char *format
} }
static int _smartdns_child_pid = 0; static int _smartdns_child_pid = 0;
static int _smartdns_child_restart = 0;
static void _smartdns_run_as_init_sig(int sig) static void _smartdns_run_monitor_sig(int sig)
{ {
if (_smartdns_child_pid > 0) { if (_smartdns_child_pid > 0) {
if (sig == SIGHUP) {
_smartdns_child_restart = 1;
kill(_smartdns_child_pid, SIGTERM);
return;
}
kill(_smartdns_child_pid, SIGTERM); kill(_smartdns_child_pid, SIGTERM);
waitpid(_smartdns_child_pid, NULL, 0);
} }
waitpid(_smartdns_child_pid, NULL, 0);
_exit(0); _exit(0);
} }
static int _smartdns_run_as_init(int restart_when_crash) static smartdns_run_monitor_ret _smartdns_run_monitor(int restart_when_crash, int is_run_as_daemon)
{ {
pid_t pid; pid_t pid;
int status;
if (restart_when_crash == 0) { if (restart_when_crash == 0) {
return 0; return SMARTDNS_RUN_MONITOR_OK;
} }
pid = getpid(); if (is_run_as_daemon) {
setpgid(pid, pid); int daemon_ret = daemon_run();
if (daemon_ret != -2) {
if (daemon_ret == 0) {
return SMARTDNS_RUN_MONITOR_EXIT;
}
return SMARTDNS_RUN_MONITOR_ERROR;
}
}
daemon_kickoff(0, 1);
restart: restart:
pid = fork(); pid = fork();
if (pid < 0) { if (pid < 0) {
fprintf(stderr, "fork failed, %s\n", strerror(errno)); fprintf(stderr, "fork failed, %s\n", strerror(errno));
return -1; return SMARTDNS_RUN_MONITOR_ERROR;
} else if (pid == 0) { } else if (pid == 0) {
return 0; return SMARTDNS_RUN_MONITOR_OK;
} }
_smartdns_child_pid = pid; _smartdns_child_pid = pid;
signal(SIGTERM, _smartdns_run_as_init_sig); signal(SIGTERM, _smartdns_run_monitor_sig);
signal(SIGHUP, _smartdns_run_monitor_sig);
while (true) { while (true) {
pid = waitpid(-1, NULL, 0); pid = waitpid(-1, &status, 0);
if (pid == _smartdns_child_pid) { if (pid == _smartdns_child_pid) {
goto restart; int need_restart = 0;
char signalmsg[64] = {0};
if (_smartdns_child_restart == 1) {
_smartdns_child_restart = 0;
goto restart;
}
if (WEXITSTATUS(status) == SMARTDNS_CRASH_CODE) {
need_restart = 1;
} else if (WEXITSTATUS(status) == 255) {
fprintf(stderr, "run daemon failed, please check log.\n");
} else if (WIFSIGNALED(status)) {
switch (WTERMSIG(status)) {
case SIGSEGV:
case SIGABRT:
case SIGBUS:
case SIGILL:
case SIGFPE:
snprintf(signalmsg, sizeof(signalmsg), " with signal %d", WTERMSIG(status));
need_restart = 1;
break;
default:
break;
}
}
if (need_restart == 1) {
printf("smartdns crashed%s, restart...\n", signalmsg);
goto restart;
}
break;
} }
if (pid < 0) { if (pid < 0) {
@@ -820,7 +885,7 @@ restart:
} }
} }
return -1; return SMARTDNS_RUN_MONITOR_ERROR;
} }
#ifdef TEST #ifdef TEST
@@ -932,7 +997,11 @@ int main(int argc, char *argv[])
} }
} }
if (_smartdns_run_as_init(restart_when_crash) != 0) { smartdns_run_monitor_ret init_ret = _smartdns_run_monitor(restart_when_crash, is_run_as_daemon);
if (init_ret != SMARTDNS_RUN_MONITOR_OK) {
if (init_ret == SMARTDNS_RUN_MONITOR_EXIT) {
return 0;
}
return 1; return 1;
} }
@@ -946,7 +1015,7 @@ int main(int argc, char *argv[])
goto errout; goto errout;
} }
if (dns_no_daemon) { if (dns_no_daemon || restart_when_crash) {
is_run_as_daemon = 0; is_run_as_daemon = 0;
} }
@@ -1006,6 +1075,8 @@ int main(int argc, char *argv[])
if (ret != 0) { if (ret != 0) {
goto errout; goto errout;
} }
} else if (dns_conf_log_console == 0 && verbose_screen == 0) {
daemon_close_stdfds();
} }
smartdns_test_notify(1); smartdns_test_notify(1);
@@ -1019,5 +1090,5 @@ errout:
} }
smartdns_test_notify(2); smartdns_test_notify(2);
_smartdns_exit(); _smartdns_exit();
return 1; return ret;
} }

View File

@@ -1632,6 +1632,23 @@ errout:
return; return;
} }
void daemon_close_stdfds(void)
{
int fd_null = open("/dev/null", O_RDWR);
if (fd_null < 0) {
fprintf(stderr, "open /dev/null failed, %s\n", strerror(errno));
return;
}
dup2(fd_null, STDIN_FILENO);
dup2(fd_null, STDOUT_FILENO);
dup2(fd_null, STDERR_FILENO);
if (fd_null > 2) {
close(fd_null);
}
}
int daemon_kickoff(int status, int no_close) int daemon_kickoff(int status, int no_close)
{ {
struct daemon_msg msg; struct daemon_msg msg;
@@ -1650,19 +1667,7 @@ int daemon_kickoff(int status, int no_close)
} }
if (no_close == 0) { if (no_close == 0) {
int fd_null = open("/dev/null", O_RDWR); daemon_close_stdfds();
if (fd_null < 0) {
fprintf(stderr, "open /dev/null failed, %s\n", strerror(errno));
return -1;
}
dup2(fd_null, STDIN_FILENO);
dup2(fd_null, STDOUT_FILENO);
dup2(fd_null, STDERR_FILENO);
if (fd_null > 2) {
close(fd_null);
}
} }
close(daemon_fd); close(daemon_fd);

View File

@@ -153,6 +153,8 @@ int daemon_kickoff(int status, int no_close);
int daemon_keepalive(void); int daemon_keepalive(void);
void daemon_close_stdfds(void);
int write_file(const char *filename, void *data, int data_len); int write_file(const char *filename, void *data, int data_len);
int dns_packet_save(const char *dir, const char *type, const char *from, const void *packet, int packet_len); int dns_packet_save(const char *dir, const char *type, const char *from, const void *packet, int packet_len);