Browse Source

update: stable daemon

dev
dnomd343 3 years ago
parent
commit
f6a17f926c
  1. 10
      include/exit_code.h
  2. 6
      src/cleardns.c
  3. 17
      src/common.c
  4. 62
      src/process.c

10
include/exit_code.h

@ -0,0 +1,10 @@
#ifndef _EXIT_CODE_H_
#define _EXIT_CODE_H_
#define EXIT_NORMAL 0
#define EXIT_FILE_ERROR 1
#define EXIT_FORK_ERROR 2
#define EXIT_EXEC_ERROR 3
#define EXIT_WAIT_ERROR 4
#endif

6
src/cleardns.c

@ -22,7 +22,7 @@ void show_command(char *title, char **command) {
fprintf(stderr, "\"\n"); fprintf(stderr, "\"\n");
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) { // ClearDNS server
int debug_mode = 0; int debug_mode = 0;
fprintf(stderr, "[ClearDNS] Server start.\n"); fprintf(stderr, "[ClearDNS] Server start.\n");
for (char **p = argv; p < argv + argc; ++p) { for (char **p = argv; p < argv + argc; ++p) {
@ -41,7 +41,7 @@ int main(int argc, char *argv[]) {
show_command("[ClearDNS] dnsproxy (foreign)", foreign_dnsproxy_command); show_command("[ClearDNS] dnsproxy (foreign)", foreign_dnsproxy_command);
} }
init_server(init_script, custom_script); init_server(init_script, custom_script); // run init script and custom script
server_daemon(); server_daemon(); // run as daemon to manage process in docker
return 0; return 0;
} }

17
src/common.c

@ -2,6 +2,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "cJSON.h" #include "cJSON.h"
#include "exit_code.h"
char **crond_command = NULL; char **crond_command = NULL;
char **adguard_command = NULL; char **adguard_command = NULL;
@ -17,7 +18,7 @@ void load_start_command(char *adguard_workdir, char *overture_config, char *upst
void error_exit(char *message) { // exit with code 1 void error_exit(char *message) { // exit with code 1
fprintf(stderr, "[ClearDNS] %s\n", message); fprintf(stderr, "[ClearDNS] %s\n", message);
exit(1); exit(EXIT_FILE_ERROR);
} }
char* read_file(char *file_name) { // read file content char* read_file(char *file_name) { // read file content
@ -88,8 +89,10 @@ char** dnsproxy_config(char *port, cJSON *json, int is_debug) { // generate dnsp
command_list = command_add_field(command_list, bootstrap_dns); command_list = command_add_field(command_list, bootstrap_dns);
} }
if (primary_dns != NULL) { // add primary DNS server if (primary_dns == NULL) { // primary DNS server required
while (primary_dns != NULL) { // iterate over server list error_exit("Miss primary DNS server.");
}
while (primary_dns != NULL) { // iterate over primary DNS server list
if (!cJSON_IsString(primary_dns)) { if (!cJSON_IsString(primary_dns)) {
error_exit("DNS Server should be a string."); error_exit("DNS Server should be a string.");
} }
@ -97,12 +100,8 @@ char** dnsproxy_config(char *port, cJSON *json, int is_debug) { // generate dnsp
command_list = command_add_field(command_list, primary_dns->valuestring); command_list = command_add_field(command_list, primary_dns->valuestring);
primary_dns = primary_dns->next; primary_dns = primary_dns->next;
} }
} else {
error_exit("Miss primary DNS server."); // primary DNS server required
}
if (fallback_dns != NULL) { // add fallback DNS server while (fallback_dns != NULL) { // iterate over fallback DNS server list
while (fallback_dns != NULL) { // iterate over server list
if (!cJSON_IsString(fallback_dns)) { if (!cJSON_IsString(fallback_dns)) {
error_exit("DNS Server should be a string."); error_exit("DNS Server should be a string.");
} }
@ -110,12 +109,10 @@ char** dnsproxy_config(char *port, cJSON *json, int is_debug) { // generate dnsp
command_list = command_add_field(command_list, fallback_dns->valuestring); command_list = command_add_field(command_list, fallback_dns->valuestring);
fallback_dns = fallback_dns->next; fallback_dns = fallback_dns->next;
} }
}
if (is_debug) { // debug mode if (is_debug) { // debug mode
command_list = command_add_field(command_list, "--verbose"); command_list = command_add_field(command_list, "--verbose");
} }
return command_list; return command_list;
} }

62
src/process.c

@ -1,10 +1,13 @@
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <glib.h> #include <glib.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/prctl.h> #include <sys/prctl.h>
#include "common.h" #include "common.h"
#include "exit_code.h"
int exiting = 0; int exiting = 0;
@ -14,16 +17,21 @@ pid_t overture_pid = 0;
pid_t domestic_dnsproxy_pid = 0; pid_t domestic_dnsproxy_pid = 0;
pid_t foreign_dnsproxy_pid = 0; pid_t foreign_dnsproxy_pid = 0;
void server_exit();
void get_sub_exit(); void get_sub_exit();
void server_daemon(); void server_daemon();
void get_exit_signal();
void server_exit(int exit_code);
pid_t process_exec(char **command); pid_t process_exec(char **command);
void init_server(char *init_script, char *custom_script); void init_server(char *init_script, char *custom_script);
void server_exit() { // kill sub-process and exit void get_exit_signal() { // get SIGINT or SIGTERM signal
int status, ret;
exiting = 1;
fprintf(stderr, "[ClearDNS] Get exit signal.\n"); fprintf(stderr, "[ClearDNS] Get exit signal.\n");
server_exit(EXIT_NORMAL);
}
void server_exit(int exit_code) { // kill sub process and exit
int status, ret;
exiting = 1; // set a exit flag
if (crond_pid != 0) { if (crond_pid != 0) {
fprintf(stderr, "[ClearDNS] Kill crond. (pid = %d)\n", crond_pid); fprintf(stderr, "[ClearDNS] Kill crond. (pid = %d)\n", crond_pid);
@ -49,11 +57,11 @@ void server_exit() { // kill sub-process and exit
while ((ret = wait(&status)) != -1) { while ((ret = wait(&status)) != -1) {
fprintf(stderr, "[ClearDNS] Subprocess exit. (pid = %d)\n", ret); fprintf(stderr, "[ClearDNS] Subprocess exit. (pid = %d)\n", ret);
} }
printf("[ClearDNS] Exit successfully.\n"); fprintf(stderr, "[ClearDNS] Exit successfully.\n");
exit(0); exit(exit_code);
} }
void get_sub_exit() { // catch child process die void get_sub_exit() { // catch child process exit
int ret, status; int ret, status;
int wait_time = 3; // seconds for wait before restart int wait_time = 3; // seconds for wait before restart
if (exiting) { return; } // server daemon is exiting if (exiting) { return; } // server daemon is exiting
@ -62,10 +70,10 @@ void get_sub_exit() { // catch child process die
ret = waitpid(crond_pid, &status, WNOHANG); // non-blocking ret = waitpid(crond_pid, &status, WNOHANG); // non-blocking
if (ret == -1) { if (ret == -1) {
perror("[ClearDNS] Waitpid error"); perror("[ClearDNS] Waitpid error");
server_exit(); server_exit(EXIT_WAIT_ERROR);
} else if (ret) { // process exit } else if (ret) { // process exit
crond_pid = process_exec(crond_command); crond_pid = process_exec(crond_command);
fprintf(stderr, "[ClearDNS] Catch crond exit and restart it. (pid = %d)\n", crond_pid); fprintf(stderr, "[ClearDNS] Catch crond exit and restart it. (pid = %d -> %d)\n", ret, crond_pid);
sleep(wait_time); // reduce restart frequency sleep(wait_time); // reduce restart frequency
return; return;
} }
@ -75,10 +83,10 @@ void get_sub_exit() { // catch child process die
ret = waitpid(adguard_pid, &status, WNOHANG); // non-blocking ret = waitpid(adguard_pid, &status, WNOHANG); // non-blocking
if (ret == -1) { if (ret == -1) {
perror("[ClearDNS] Waitpid error"); perror("[ClearDNS] Waitpid error");
server_exit(); server_exit(EXIT_WAIT_ERROR);
} else if (ret) { // process exit } else if (ret) { // process exit
adguard_pid = process_exec(adguard_command); adguard_pid = process_exec(adguard_command);
fprintf(stderr, "[ClearDNS] Catch AdGuardHome exit and restart it. (pid = %d)\n", adguard_pid); fprintf(stderr, "[ClearDNS] Catch AdGuardHome exit and restart it. (pid = %d -> %d)\n", ret, adguard_pid);
sleep(wait_time); // reduce restart frequency sleep(wait_time); // reduce restart frequency
return; return;
} }
@ -88,10 +96,10 @@ void get_sub_exit() { // catch child process die
ret = waitpid(overture_pid, &status, WNOHANG); // non-blocking ret = waitpid(overture_pid, &status, WNOHANG); // non-blocking
if (ret == -1) { if (ret == -1) {
perror("[ClearDNS] Waitpid error"); perror("[ClearDNS] Waitpid error");
server_exit(); server_exit(EXIT_WAIT_ERROR);
} else if (ret) { // process exit } else if (ret) { // process exit
overture_pid = process_exec(overture_command); overture_pid = process_exec(overture_command);
fprintf(stderr, "[ClearDNS] Catch overture exit and restart it. (pid = %d)\n", overture_pid); fprintf(stderr, "[ClearDNS] Catch overture exit and restart it. (pid = %d -> %d)\n", ret, overture_pid);
sleep(wait_time); // reduce restart frequency sleep(wait_time); // reduce restart frequency
return; return;
} }
@ -101,10 +109,10 @@ void get_sub_exit() { // catch child process die
ret = waitpid(domestic_dnsproxy_pid, &status, WNOHANG); // non-blocking ret = waitpid(domestic_dnsproxy_pid, &status, WNOHANG); // non-blocking
if (ret == -1) { if (ret == -1) {
perror("[ClearDNS] Waitpid error"); perror("[ClearDNS] Waitpid error");
server_exit(); server_exit(EXIT_WAIT_ERROR);
} else if (ret) { // process exit } else if (ret) { // process exit
domestic_dnsproxy_pid = process_exec(domestic_dnsproxy_command); domestic_dnsproxy_pid = process_exec(domestic_dnsproxy_command);
fprintf(stderr, "[ClearDNS] Catch domestic dnsproxy exit and restart it. (pid = %d)\n", domestic_dnsproxy_pid); fprintf(stderr, "[ClearDNS] Catch domestic dnsproxy exit and restart it. (pid = %d -> %d)\n", ret, domestic_dnsproxy_pid);
sleep(wait_time); // reduce restart frequency sleep(wait_time); // reduce restart frequency
return; return;
} }
@ -114,10 +122,10 @@ void get_sub_exit() { // catch child process die
ret = waitpid(foreign_dnsproxy_pid, &status, WNOHANG); // non-blocking ret = waitpid(foreign_dnsproxy_pid, &status, WNOHANG); // non-blocking
if (ret == -1) { if (ret == -1) {
perror("[ClearDNS] Waitpid error"); perror("[ClearDNS] Waitpid error");
server_exit(); server_exit(EXIT_WAIT_ERROR);
} else if (ret) { // process exit } else if (ret) { // process exit
foreign_dnsproxy_pid = process_exec(foreign_dnsproxy_command); foreign_dnsproxy_pid = process_exec(foreign_dnsproxy_command);
fprintf(stderr, "[ClearDNS] Catch foreign dnsproxy exit and restart it. (pid = %d)\n", foreign_dnsproxy_pid); fprintf(stderr, "[ClearDNS] Catch foreign dnsproxy exit and restart it. (pid = %d -> %d)\n", ret, foreign_dnsproxy_pid);
sleep(wait_time); // reduce restart frequency sleep(wait_time); // reduce restart frequency
return; return;
} }
@ -126,7 +134,7 @@ void get_sub_exit() { // catch child process die
ret = waitpid(-1, &status, WNOHANG); // waitpid for all sub-process (non-blocking) ret = waitpid(-1, &status, WNOHANG); // waitpid for all sub-process (non-blocking)
if (ret == -1) { if (ret == -1) {
perror("[ClearDNS] Waitpid error"); perror("[ClearDNS] Waitpid error");
server_exit(); server_exit(EXIT_WAIT_ERROR);
} else if (ret) { // process exit } else if (ret) { // process exit
fprintf(stderr, "[ClearDNS] Catch subprocess exit. (pid = %d)\n", ret); fprintf(stderr, "[ClearDNS] Catch subprocess exit. (pid = %d)\n", ret);
return; return;
@ -139,12 +147,12 @@ pid_t process_exec(char **command) {
char **env = {NULL}; char **env = {NULL};
if ((pid = fork()) < 0) { if ((pid = fork()) < 0) {
perror("[ClearDNS] Fork error"); perror("[ClearDNS] Fork error");
exit(2); server_exit(EXIT_FORK_ERROR);
} else if (pid == 0) { // child process } else if (pid == 0) { // child process
prctl(PR_SET_PDEATHSIG, SIGKILL); // child process die with father process prctl(PR_SET_PDEATHSIG, SIGKILL); // child process die with father process
if (execvpe(command[0], command, env) < 0) { if (execvpe(command[0], command, env) < 0) {
perror("[ClearDNS] Exec error"); perror("[ClearDNS] Exec error");
exit(3); server_exit(EXIT_EXEC_ERROR);
} }
} }
return pid; return pid;
@ -156,12 +164,12 @@ void init_server(char *init_script, char *custom_script) { // run init script (b
if ((init_pid = fork()) < 0) { if ((init_pid = fork()) < 0) {
perror("[ClearDNS] Fork error"); perror("[ClearDNS] Fork error");
exit(2); server_exit(EXIT_FORK_ERROR);
} else if (init_pid == 0) { // child process } else if (init_pid == 0) { // child process
prctl(PR_SET_PDEATHSIG, SIGKILL); // child process die with father process prctl(PR_SET_PDEATHSIG, SIGKILL); // child process die with father process
if (execlp("/bin/sh", "/bin/sh", init_script, NULL)) { if (execlp("/bin/sh", "/bin/sh", init_script, NULL)) {
perror("[ClearDNS] Init error"); perror("[ClearDNS] Init error");
exit(3); server_exit(EXIT_EXEC_ERROR);
} }
} }
wait(&status); // blocking wait wait(&status); // blocking wait
@ -171,12 +179,12 @@ void init_server(char *init_script, char *custom_script) { // run init script (b
fprintf(stderr, "[ClearDNS] Running custom script.\n"); fprintf(stderr, "[ClearDNS] Running custom script.\n");
if ((custom_pid = fork()) < 0) { if ((custom_pid = fork()) < 0) {
perror("[ClearDNS] Fork error"); perror("[ClearDNS] Fork error");
exit(2); server_exit(EXIT_FORK_ERROR);
} else if (custom_pid == 0) { // child process } else if (custom_pid == 0) { // child process
prctl(PR_SET_PDEATHSIG, SIGKILL); // child process die with father process prctl(PR_SET_PDEATHSIG, SIGKILL); // child process die with father process
if (execlp("/bin/sh", "/bin/sh", custom_script, NULL)) { if (execlp("/bin/sh", "/bin/sh", custom_script, NULL)) {
perror("[ClearDNS] Custom script error"); perror("[ClearDNS] Custom script error");
exit(3); server_exit(EXIT_EXEC_ERROR);
} }
} }
sleep(1); // wait a moment sleep(1); // wait a moment
@ -185,8 +193,8 @@ void init_server(char *init_script, char *custom_script) { // run init script (b
void server_daemon() { // run as a daemon of cleardns void server_daemon() { // run as a daemon of cleardns
int wait_us_time = 200 * 1000; // 200ms int wait_us_time = 200 * 1000; // 200ms
signal(SIGINT, server_exit); // catch Ctrl + C (2) signal(SIGINT, get_exit_signal); // catch Ctrl + C (2)
signal(SIGTERM, server_exit); // catch exit signal (15) signal(SIGTERM, get_exit_signal); // catch exit signal (15)
signal(SIGCHLD, get_sub_exit); // callback when child process die signal(SIGCHLD, get_sub_exit); // callback when child process die
crond_pid = process_exec(crond_command); crond_pid = process_exec(crond_command);

Loading…
Cancel
Save