diff options
author | Kozlov Dmitry <xeb@mail.ru> | 2012-07-10 18:58:53 +0400 |
---|---|---|
committer | Kozlov Dmitry <xeb@mail.ru> | 2012-07-10 18:58:53 +0400 |
commit | 80c32d237e01b1c05663ccfa34003d2f49aa7eee (patch) | |
tree | a49da21b5219e4bc89d9794918f054f3620cb140 /accel-pppd/main.c | |
parent | 64b5b693764c4f36870fd988ccbb53bcb188e74d (diff) | |
download | accel-ppp-80c32d237e01b1c05663ccfa34003d2f49aa7eee.tar.gz accel-ppp-80c32d237e01b1c05663ccfa34003d2f49aa7eee.zip |
initial session backup implementation
Diffstat (limited to 'accel-pppd/main.c')
-rw-r--r-- | accel-pppd/main.c | 177 |
1 files changed, 169 insertions, 8 deletions
diff --git a/accel-pppd/main.c b/accel-pppd/main.c index e153caf4..9e515564 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 char *exec_file; static void change_limits(void) { @@ -50,19 +62,138 @@ 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]; + + sprintf(path, "/proc/%u/fd", getpid()); + + dirp = opendir(path); + if (!dirp) + return; + + while (1) { + if (readdir_r(dirp, &ent, &res)) + return; + if (!res) + break; + close((unsigned long)atol(ent.d_name)); + } + + closedir(dirp); +} + +void core_restart(int soft) +{ + char fname[128]; + int fd, n; + char cmdline[ARG_MAX]; + char *args[16]; + char *ptr = cmdline, *endptr; + sigset_t set; + + if (fork()) { + close_all_fd(); + return; + } + + sigfillset(&set); + pthread_sigmask(SIG_SETMASK, &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) { + args[n++] = ptr; + while (ptr < endptr && *ptr++); + } + + args[n++] = NULL; + +#ifdef USE_BACKUP + if (soft) + backup_restore_fd(); + else +#endif + if (fork()) { + close_all_fd(); + _exit(0); + } + + + while (1) { + sleep(3); + execv(args[0], args); + } +} + +static void sigsegv(int num) +{ + char cmd[PATH_MAX]; + char fname[PATH_MAX]; + struct rlimit lim; + +#ifdef USE_BACKUP + core_restart(1); +#else + core_restart(0); +#endif + + if (conf_dump) { + FILE *f; + unsigned int t = time(NULL); + sprintf(fname, "%s/cmd-%u", conf_dump, t); + f = fopen(fname, "w"); + if (!f) + goto out; + fprintf(f, "thread apply all bt full\ndetach\nquit\n"); + fclose(f); + + sprintf(cmd, "gdb -x %s %s %d > %s/dump-%u", fname, exec_file, getpid(), conf_dump, t); + system(cmd); + unlink(fname); + + lim.rlim_cur = RLIM_INFINITY; + lim.rlim_max = RLIM_INFINITY; + + setrlimit(RLIMIT_CORE, &lim); + + chdir(conf_dump); + } + +out: + 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); +#ifdef USE_BACKUP + int internal = 0; +#endif if (argc < 2) goto usage; + exec_file = argv[0]; + for(i = 1; i < argc; i++) { if (!strcmp(argv[i], "-d")) goto_daemon = 1; @@ -74,16 +205,38 @@ 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); } } if (!conf_file) goto usage; + + if (pid_file) { + FILE *f = fopen(pid_file, "r"); + if (f) { + fscanf(f, "%u", &pid); + fclose(f); + } +#ifdef USE_BACKUP + internal = pid == getppid(); +#endif + /*if (pid) { + printf("%i %i %i\n", pid, getppid(), getpid()); + return 0; + }*/ + } 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 +274,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); @@ -151,7 +308,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); |