summaryrefslogtreecommitdiff
path: root/accel-pppd/main.c
diff options
context:
space:
mode:
authorKozlov Dmitry <xeb@mail.ru>2012-07-10 18:58:53 +0400
committerKozlov Dmitry <xeb@mail.ru>2012-07-10 18:58:53 +0400
commit80c32d237e01b1c05663ccfa34003d2f49aa7eee (patch)
treea49da21b5219e4bc89d9794918f054f3620cb140 /accel-pppd/main.c
parent64b5b693764c4f36870fd988ccbb53bcb188e74d (diff)
downloadaccel-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.c177
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);