diff options
Diffstat (limited to 'accel-pppd/main.c')
-rw-r--r-- | accel-pppd/main.c | 190 |
1 files changed, 179 insertions, 11 deletions
diff --git a/accel-pppd/main.c b/accel-pppd/main.c index e153caf..1418060 100644 --- a/accel-pppd/main.c +++ b/accel-pppd/main.c @@ -4,6 +4,11 @@ #include <stdlib.h> #include <stdio.h> #include <errno.h> +#include <fcntl.h> +#include <time.h> +#include <limits.h> +#include <malloc.h> +#include <dirent.h> #include <sys/stat.h> #include <sys/mman.h> #include <sys/resource.h> @@ -13,9 +18,16 @@ #include "memdebug.h" #include "log.h" #include "events.h" +#include "backup.h" + +#ifndef ARG_MAX +#define ARG_MAX 128*1024 +#endif static char *pid_file; static char *conf_file; +static char *conf_dump; +static sigset_t orig_set; static void change_limits(void) { @@ -50,15 +62,150 @@ static void config_reload_notify(int r) if (!r) triton_event_fire(EV_CONFIG_RELOAD, NULL); } + static void config_reload(int num) { triton_conf_reload(config_reload_notify); } +/*static void close_all_fd(void) +{ + DIR *dirp; + struct dirent ent, *res; + char path[128]; + int fd; + + sprintf(path, "/proc/%u/fd", getpid()); + + dirp = opendir(path); + if (!dirp) + return; + + while (1) { + if (readdir_r(dirp, &ent, &res)) + return; + if (!res) + break; + + fd = atol(ent.d_name); + if (fd > 2) + close(fd); + } + + closedir(dirp); +}*/ + +void core_restart(int soft) +{ + char fname[128]; + int fd, n, f = 0; + char cmdline[ARG_MAX]; + char exe[PATH_MAX]; + char *argv[16]; + char *ptr = cmdline, *endptr; + + if (fork()) { + //close_all_fd(); + return; + } + + pthread_sigmask(SIG_SETMASK, &orig_set, NULL); + + sprintf(fname, "/proc/%i/cmdline", getpid()); + + fd = open(fname, O_RDONLY); + n = read(fd, cmdline, ARG_MAX); + + endptr = ptr + n; + + n = 0; + while (ptr < endptr && n < 14) { + if (strcmp(ptr, "--internal")) + argv[n++] = ptr; + else if (soft) { + f = 1; + argv[n++] = ptr; + } + + while (ptr < endptr && *ptr++); + } + +#ifdef USE_BACKUP + if (soft) + backup_restore_fd(); +#endif + + sprintf(exe, "/proc/%u/exe", getpid()); + readlink(exe, exe, PATH_MAX); + + if (!f) + argv[n++] = "--internal"; + + argv[n++] = NULL; + + while (1) { + execv(exe, argv); + sleep(3); + } +} + +static void sigsegv(int num) +{ + char cmd[PATH_MAX]; + char fname[128]; + char exec_file[PATH_MAX]; + struct rlimit lim; + + pthread_sigmask(SIG_SETMASK, &orig_set, NULL); + + if (conf_dump) { + FILE *f; + unsigned int t = time(NULL); + + chdir(conf_dump); + + sprintf(fname, "cmd-%u", t); + f = fopen(fname, "w"); + if (!f) + goto out; + fprintf(f, "thread apply all bt full\ndetach\nquit\n"); + fclose(f); + + sprintf(exec_file, "/proc/%u/exe", getpid()); + readlink(exec_file, exec_file, PATH_MAX); + + sprintf(cmd, "gdb -x %s %s %d > dump-%u", fname, exec_file, getpid(), t); + + system(cmd); + + unlink(fname); + } + +out: +#ifdef USE_BACKUP + core_restart(1); +#else + core_restart(0); +#endif + + if (conf_dump) { + lim.rlim_cur = RLIM_INFINITY; + lim.rlim_max = RLIM_INFINITY; + + setrlimit(RLIMIT_CORE, &lim); + } + + abort(); +} + int main(int argc, char **argv) { sigset_t set; - int i, sig, goto_daemon = 0; + int i, sig, goto_daemon = 0, len; + pid_t pid = 0; + struct sigaction sa; + int pagesize = sysconf(_SC_PAGE_SIZE); + int internal = 0; if (argc < 2) goto usage; @@ -74,16 +221,29 @@ int main(int argc, char **argv) if (i == argc - 1) goto usage; conf_file = argv[++i]; - } + } else if (!strcmp(argv[i], "--dump")) { + if (i == argc - 1) + goto usage; + len = (strlen(argv[i + 1]) / pagesize + 1) * pagesize; + conf_dump = memalign(pagesize, len); + strcpy(conf_dump, argv[++i]); + mprotect(conf_dump, len, PROT_READ); + } else if (!strcmp(argv[i], "--internal")) + internal = 1; } if (!conf_file) goto usage; - + + if (internal) { + while (getppid() != 1) + sleep(1); + } + if (triton_init(conf_file)) _exit(EXIT_FAILURE); - if (goto_daemon) { + if (goto_daemon && pid != getpid()) { /*pid_t pid = fork(); if (pid > 0) _exit(EXIT_SUCCESS); @@ -121,15 +281,19 @@ int main(int argc, char **argv) triton_run(); - sigfillset(&set); - struct sigaction sa = { - .sa_handler = config_reload, - .sa_mask = set, - }; + sigfillset(&set); + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = config_reload; + sa.sa_mask = set; sigaction(SIGUSR1, &sa, NULL); + + sa.sa_handler = sigsegv; + sa.sa_mask = set; + sigaction(SIGSEGV, &sa, NULL); + sigdelset(&set, SIGKILL); sigdelset(&set, SIGSTOP); sigdelset(&set, SIGSEGV); @@ -142,7 +306,7 @@ int main(int argc, char **argv) sigdelset(&set, SIGUSR1); sigdelset(&set, 35); sigdelset(&set, 36); - pthread_sigmask(SIG_SETMASK, &set, NULL); + pthread_sigmask(SIG_SETMASK, &set, &orig_set); sigemptyset(&set); //sigaddset(&set, SIGINT); @@ -151,7 +315,11 @@ int main(int argc, char **argv) sigaddset(&set, SIGILL); sigaddset(&set, SIGFPE); sigaddset(&set, SIGBUS); - + +#ifdef USE_BACKUP + backup_restore(internal); +#endif + sigwait(&set, &sig); log_info1("terminate, sig = %i\n", sig); |