diff --git a/Dockerfile b/Dockerfile index d15ea74..dfb79b5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -33,8 +33,9 @@ cd /tmp/AdGuardHome/ && git checkout ${ADGUARD_VERSION} && \ make CHANNEL="release" VERSION=${ADGUARD_VERSION} && \ mv ./AdGuardHome /tmp/release/ && \ \ -cd /tmp/release/ && strip cleardns && \ -upx -9 AdGuardHome && upx -9 dnsproxy && upx -9 overture +cd /tmp/release/ && \ +strip cleardns && \ +upx -9 AdGuardHome dnsproxy overture FROM alpine:3.15 as asset COPY . /tmp/ClearDNS @@ -55,4 +56,3 @@ COPY --from=asset /tmp/asset / RUN apk add --no-cache ca-certificates glib && \ echo -e "0\t4\t*\t*\t*\t/etc/overture/update.sh" > /var/spool/cron/crontabs/root ENTRYPOINT ["cleardns"] -EXPOSE 53/udp 53/tcp 80/tcp diff --git a/src/process.c b/src/process.c index a36b0ab..aefa793 100644 --- a/src/process.c +++ b/src/process.c @@ -9,8 +9,17 @@ #include "common.h" #include "exit_code.h" +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + int exiting = 0; +pid_t custom_pgid = 0; pid_t adguard_pid = 0; pid_t overture_pid = 0; pid_t domestic_dnsproxy_pid = 0; @@ -20,7 +29,7 @@ void get_sub_exit(); 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, int is_new_group); void init_server(char *init_script, char *custom_script); void get_exit_signal() { // get SIGINT or SIGTERM signal @@ -61,6 +70,20 @@ void server_exit(int exit_code) { // kill sub process and exit ret = waitpid(foreign_dnsproxy_pid, &status, 0); // blocking fprintf(stderr, "[ClearDNS] foreign dnsproxy exit. (pid = %d)\n", ret); + if (custom_pgid != 0) { + ret = waitpid(-custom_pgid, &status, WNOHANG); + if (ret == 0) { // custom script still running + fprintf(stderr, "[ClearDNS] Kill custom script.\n"); + kill(-custom_pgid, SIGTERM); // kill process group + } + } + + fprintf(stderr, "[ClearDNS] Kill all subprocess.\n"); + kill(-1, SIGTERM); // send kill signal to all process + while ((ret = wait(&status)) != -1) { + fprintf(stderr, "[ClearDNS] Subprocess exit. (pid = %d)\n", ret); + } + fprintf(stderr, "[ClearDNS] Exit successfully.\n"); exit(exit_code); } @@ -76,7 +99,7 @@ void get_sub_exit() { // catch child process exit perror("[ClearDNS] Waitpid error"); server_exit(EXIT_WAIT_ERROR); } else if (ret) { // process exit - adguard_pid = process_exec(adguard_command); + adguard_pid = process_exec(adguard_command, FALSE); fprintf(stderr, "[ClearDNS] Catch AdGuardHome exit and restart it. (pid = %d -> %d)\n", ret, adguard_pid); sleep(wait_time); // reduce restart frequency return; @@ -89,7 +112,7 @@ void get_sub_exit() { // catch child process exit perror("[ClearDNS] Waitpid error"); server_exit(EXIT_WAIT_ERROR); } else if (ret) { // process exit - overture_pid = process_exec(overture_command); + overture_pid = process_exec(overture_command, FALSE); fprintf(stderr, "[ClearDNS] Catch overture exit and restart it. (pid = %d -> %d)\n", ret, overture_pid); sleep(wait_time); // reduce restart frequency return; @@ -102,7 +125,7 @@ void get_sub_exit() { // catch child process exit perror("[ClearDNS] Waitpid error"); server_exit(EXIT_WAIT_ERROR); } else if (ret) { // process exit - domestic_dnsproxy_pid = process_exec(domestic_dnsproxy_command); + domestic_dnsproxy_pid = process_exec(domestic_dnsproxy_command, FALSE); fprintf(stderr, "[ClearDNS] Catch domestic dnsproxy exit and restart it. (pid = %d -> %d)\n", ret, domestic_dnsproxy_pid); sleep(wait_time); // reduce restart frequency return; @@ -115,7 +138,7 @@ void get_sub_exit() { // catch child process exit perror("[ClearDNS] Waitpid error"); server_exit(EXIT_WAIT_ERROR); } else if (ret) { // process exit - foreign_dnsproxy_pid = process_exec(foreign_dnsproxy_command); + foreign_dnsproxy_pid = process_exec(foreign_dnsproxy_command, FALSE); fprintf(stderr, "[ClearDNS] Catch foreign dnsproxy exit and restart it. (pid = %d -> %d)\n", ret, foreign_dnsproxy_pid); sleep(wait_time); // reduce restart frequency return; @@ -133,13 +156,14 @@ void get_sub_exit() { // catch child process exit fprintf(stderr, "[ClearDNS] Subprocess not found.\n"); // get SIGCHLD signal but not exited subprocess found } -pid_t process_exec(char **command) { +pid_t process_exec(char **command, int is_new_group) { pid_t pid; char **env = {NULL}; if ((pid = fork()) < 0) { perror("[ClearDNS] Fork error"); server_exit(EXIT_FORK_ERROR); } else if (pid == 0) { // child process + if (is_new_group) { setpgrp(); } // new process group prctl(PR_SET_PDEATHSIG, SIGKILL); // child process die with father process if (execvpe(command[0], command, env) < 0) { perror("[ClearDNS] Exec error"); @@ -156,7 +180,7 @@ void init_server(char *init_script, char *custom_script) { // run init script (b char *custom_command[] = {"sh", custom_script, NULL}; fprintf(stderr, "[ClearDNS] Start init process.\n"); - pid = process_exec(init_command); + pid = process_exec(init_command, FALSE); wait(&status); // blocking wait fprintf(stderr, "[ClearDNS] Init complete. (pid = %d)\n", pid); // init process @@ -164,32 +188,32 @@ void init_server(char *init_script, char *custom_script) { // run init script (b signal(SIGTERM, get_exit_signal); // catch exit signal (15) signal(SIGCHLD, get_sub_exit); // callback when child process die - pid = process_exec(crond_command); + pid = process_exec(crond_command, FALSE); fprintf(stderr, "[ClearDNS] Crond load success. (pid = %d)\n", pid); // crond process if (access(custom_script, F_OK) >= 0) { // custom script exist - pid = process_exec(custom_command); - fprintf(stderr, "[ClearDNS] Custom script is working. (pid = %d)\n", pid); // custom process - sleep(1); // wait a moment + custom_pgid = process_exec(custom_command, TRUE); + fprintf(stderr, "[ClearDNS] Custom script is working. (pgid = %d)\n", custom_pgid); // custom process + usleep(200000); // wait a moment (200ms) } } void server_daemon() { // run as a daemon of ClearDNS - int wait_us_time = 100000; // 100ms + int wait_us_time = 200000; // 200ms - adguard_pid = process_exec(adguard_command); + adguard_pid = process_exec(adguard_command, FALSE); fprintf(stderr, "[ClearDNS] Exec AdGuardHome. (pid = %d)\n", adguard_pid); usleep(wait_us_time); - overture_pid = process_exec(overture_command); + overture_pid = process_exec(overture_command, FALSE); fprintf(stderr, "[ClearDNS] Exec overture. (pid = %d)\n", overture_pid); usleep(wait_us_time); - domestic_dnsproxy_pid = process_exec(domestic_dnsproxy_command); + domestic_dnsproxy_pid = process_exec(domestic_dnsproxy_command, FALSE); fprintf(stderr, "[ClearDNS] Exec domestic dnsproxy. (pid = %d)\n", domestic_dnsproxy_pid); usleep(wait_us_time); - foreign_dnsproxy_pid = process_exec(foreign_dnsproxy_command); + foreign_dnsproxy_pid = process_exec(foreign_dnsproxy_command, FALSE); fprintf(stderr, "[ClearDNS] Exec foreign dnsproxy. (pid = %d)\n", foreign_dnsproxy_pid); usleep(wait_us_time);