Browse Source

fix: kill other sub-process

dev
dnomd343 3 years ago
parent
commit
fd24a33218
  1. 6
      Dockerfile
  2. 56
      src/process.c

6
Dockerfile

@ -33,8 +33,9 @@ cd /tmp/AdGuardHome/ && git checkout ${ADGUARD_VERSION} && \
make CHANNEL="release" VERSION=${ADGUARD_VERSION} && \ make CHANNEL="release" VERSION=${ADGUARD_VERSION} && \
mv ./AdGuardHome /tmp/release/ && \ mv ./AdGuardHome /tmp/release/ && \
\ \
cd /tmp/release/ && strip cleardns && \ cd /tmp/release/ && \
upx -9 AdGuardHome && upx -9 dnsproxy && upx -9 overture strip cleardns && \
upx -9 AdGuardHome dnsproxy overture
FROM alpine:3.15 as asset FROM alpine:3.15 as asset
COPY . /tmp/ClearDNS COPY . /tmp/ClearDNS
@ -55,4 +56,3 @@ COPY --from=asset /tmp/asset /
RUN apk add --no-cache ca-certificates glib && \ 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 echo -e "0\t4\t*\t*\t*\t/etc/overture/update.sh" > /var/spool/cron/crontabs/root
ENTRYPOINT ["cleardns"] ENTRYPOINT ["cleardns"]
EXPOSE 53/udp 53/tcp 80/tcp

56
src/process.c

@ -9,8 +9,17 @@
#include "common.h" #include "common.h"
#include "exit_code.h" #include "exit_code.h"
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
int exiting = 0; int exiting = 0;
pid_t custom_pgid = 0;
pid_t adguard_pid = 0; pid_t adguard_pid = 0;
pid_t overture_pid = 0; pid_t overture_pid = 0;
pid_t domestic_dnsproxy_pid = 0; pid_t domestic_dnsproxy_pid = 0;
@ -20,7 +29,7 @@ void get_sub_exit();
void server_daemon(); void server_daemon();
void get_exit_signal(); void get_exit_signal();
void server_exit(int exit_code); 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 init_server(char *init_script, char *custom_script);
void get_exit_signal() { // get SIGINT or SIGTERM signal 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 ret = waitpid(foreign_dnsproxy_pid, &status, 0); // blocking
fprintf(stderr, "[ClearDNS] foreign dnsproxy exit. (pid = %d)\n", ret); 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"); fprintf(stderr, "[ClearDNS] Exit successfully.\n");
exit(exit_code); exit(exit_code);
} }
@ -76,7 +99,7 @@ void get_sub_exit() { // catch child process exit
perror("[ClearDNS] Waitpid error"); perror("[ClearDNS] Waitpid error");
server_exit(EXIT_WAIT_ERROR); 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, FALSE);
fprintf(stderr, "[ClearDNS] Catch AdGuardHome exit and restart it. (pid = %d -> %d)\n", ret, 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;
@ -89,7 +112,7 @@ void get_sub_exit() { // catch child process exit
perror("[ClearDNS] Waitpid error"); perror("[ClearDNS] Waitpid error");
server_exit(EXIT_WAIT_ERROR); 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, FALSE);
fprintf(stderr, "[ClearDNS] Catch overture exit and restart it. (pid = %d -> %d)\n", ret, 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;
@ -102,7 +125,7 @@ void get_sub_exit() { // catch child process exit
perror("[ClearDNS] Waitpid error"); perror("[ClearDNS] Waitpid error");
server_exit(EXIT_WAIT_ERROR); 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, FALSE);
fprintf(stderr, "[ClearDNS] Catch domestic dnsproxy exit and restart it. (pid = %d -> %d)\n", ret, 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;
@ -115,7 +138,7 @@ void get_sub_exit() { // catch child process exit
perror("[ClearDNS] Waitpid error"); perror("[ClearDNS] Waitpid error");
server_exit(EXIT_WAIT_ERROR); 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, FALSE);
fprintf(stderr, "[ClearDNS] Catch foreign dnsproxy exit and restart it. (pid = %d -> %d)\n", ret, 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;
@ -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 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; pid_t pid;
char **env = {NULL}; char **env = {NULL};
if ((pid = fork()) < 0) { if ((pid = fork()) < 0) {
perror("[ClearDNS] Fork error"); perror("[ClearDNS] Fork error");
server_exit(EXIT_FORK_ERROR); server_exit(EXIT_FORK_ERROR);
} else if (pid == 0) { // child process } 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 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");
@ -156,7 +180,7 @@ void init_server(char *init_script, char *custom_script) { // run init script (b
char *custom_command[] = {"sh", custom_script, NULL}; char *custom_command[] = {"sh", custom_script, NULL};
fprintf(stderr, "[ClearDNS] Start init process.\n"); fprintf(stderr, "[ClearDNS] Start init process.\n");
pid = process_exec(init_command); pid = process_exec(init_command, FALSE);
wait(&status); // blocking wait wait(&status); // blocking wait
fprintf(stderr, "[ClearDNS] Init complete. (pid = %d)\n", pid); // init process 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(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
pid = process_exec(crond_command); pid = process_exec(crond_command, FALSE);
fprintf(stderr, "[ClearDNS] Crond load success. (pid = %d)\n", pid); // crond process fprintf(stderr, "[ClearDNS] Crond load success. (pid = %d)\n", pid); // crond process
if (access(custom_script, F_OK) >= 0) { // custom script exist if (access(custom_script, F_OK) >= 0) { // custom script exist
pid = process_exec(custom_command); custom_pgid = process_exec(custom_command, TRUE);
fprintf(stderr, "[ClearDNS] Custom script is working. (pid = %d)\n", pid); // custom process fprintf(stderr, "[ClearDNS] Custom script is working. (pgid = %d)\n", custom_pgid); // custom process
sleep(1); // wait a moment usleep(200000); // wait a moment (200ms)
} }
} }
void server_daemon() { // run as a daemon of ClearDNS 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); fprintf(stderr, "[ClearDNS] Exec AdGuardHome. (pid = %d)\n", adguard_pid);
usleep(wait_us_time); 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); fprintf(stderr, "[ClearDNS] Exec overture. (pid = %d)\n", overture_pid);
usleep(wait_us_time); 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); fprintf(stderr, "[ClearDNS] Exec domestic dnsproxy. (pid = %d)\n", domestic_dnsproxy_pid);
usleep(wait_us_time); 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); fprintf(stderr, "[ClearDNS] Exec foreign dnsproxy. (pid = %d)\n", foreign_dnsproxy_pid);
usleep(wait_us_time); usleep(wait_us_time);

Loading…
Cancel
Save