From 92f7f79eb9535a281cab710eedb9878c74b950b8 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 25 Jan 2011 11:02:12 +1030 Subject: [PATCH] lca2011: dump, re-exec with --restore on restart. --- ccan/oserver/_info | 17 ++++++++++++++++- ccan/oserver/oserver.c | 12 +++++++++++- ccan/oserver/oserver.h | 5 +++-- ccan/oserver/oserver_types.h | 2 ++ ccan/oserver/test/run-one-client-disconnect.c | 2 +- ccan/oserver/test/run.c | 2 +- 6 files changed, 34 insertions(+), 6 deletions(-) diff --git a/ccan/oserver/_info b/ccan/oserver/_info index 7d05837..7bfaa3b 100644 --- a/ccan/oserver/_info +++ b/ccan/oserver/_info @@ -16,21 +16,36 @@ * #include * #include * + * #define STATE_FILE "/var/run/oserver/dump" + * * int main(int argc, char *argv[]) * { * struct tevent_context *ev = tevent_context_init(NULL); * unsigned int port = OSERVER_PORT; + * bool restore = false; + * char **restore_argv; + * + * // Save args before opt_parse mangles them. + * restore_argv = talloc_array(NULL, char *, argc+2); + * restore_argv[0] = argv[0]; + * restore_argv[1] = "--restore"; + * memcpy(restore_argv+2, argv+1, sizeof(argv[0])*argc); * * opt_register_noarg("--help|--usage|-h", opt_usage_and_exit, * "\nA oserver program", "Usage information"); * opt_register_arg("--port", opt_set_uintval, opt_show_uintval, * &port, "Server port number"); + * opt_register_noarg("--restore", opt_set_bool, + * &restore, opt_hidden); * * opt_parse(&argc, argv, opt_log_stderr_exit); * if (argc != 1) * opt_log_stderr_exit("Unknown extra arguments"); * - * if (!oserver_setup(ev, port, "/var/run/oserver/dump")) + * if (restore) { + * if (!oserver_restore(ev, STATE_FILE)) + * err(1, "Restoring server"); + * } else if (!oserver_setup(ev, port, STATE_FILE, restore_argv)) * err(1, "Failed to set up server"); * * while (tevent_loop_wait(ev) == 0); diff --git a/ccan/oserver/oserver.c b/ccan/oserver/oserver.c index 405a576..d4266ed 100644 --- a/ccan/oserver/oserver.c +++ b/ccan/oserver/oserver.c @@ -305,6 +305,8 @@ static void dump(struct tevent_context *ev, write(fd, str, strlen(str)); close(fd); talloc_free(str); + if (oserver->argv) + execvp(oserver->argv[0], oserver->argv); } static bool load_file(struct oserver *oserver, const char *file) @@ -385,7 +387,7 @@ struct oserver *oserver_restore(struct tevent_context *ev, const char *dumpfile) } struct oserver *oserver_setup(struct tevent_context *ev, unsigned short port, - const char *dumpfile) + const char *dumpfile, char *argv[]) { struct oserver *oserver; int one = 1; @@ -395,6 +397,14 @@ struct oserver *oserver_setup(struct tevent_context *ev, unsigned short port, } u; oserver = talloc(ev, struct oserver); + oserver->argv = argv; + if (argv) { + /* Count the terminal NULL in argv_len. */ + for (oserver->argv_len = 1; + argv[oserver->argv_len - 1]; + oserver->argv_len++); + } else + oserver->argv_len = 0; clear_clients(oserver); oserver->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (oserver->fd < 0) { diff --git a/ccan/oserver/oserver.h b/ccan/oserver/oserver.h index 06a89b2..597d7ee 100644 --- a/ccan/oserver/oserver.h +++ b/ccan/oserver/oserver.h @@ -30,6 +30,7 @@ struct oserver *oserver_restore(struct tevent_context *ev, * @ev: tevent context to use. * @port: port to use (usually OSERVER_PORT) * @dumpfile: file to save state to on SIGHUP (if non-NULL). + * @argv: arguments to re-exec on SIGHUP (if non-NULL). * * Opens a socket and binds it to @port, then sets it up to listen * for connections. talloc_free() the pointer returned to shut it down @@ -38,7 +39,7 @@ struct oserver *oserver_restore(struct tevent_context *ev, * Example: * ... * else { - * oserver = oserver_setup(ev, OSERVER_PORT, "oserver.dump"); + * oserver = oserver_setup(ev, OSERVER_PORT, "oserver.dump", argv); * if (!oserver) * err(1, "Failed to set up server"); * } @@ -46,7 +47,7 @@ struct oserver *oserver_restore(struct tevent_context *ev, * err(1, "Event loop failed"); */ struct oserver *oserver_setup(struct tevent_context *ev, unsigned short port, - const char *dumpfile); + const char *dumpfile, char *argv[]); #define OSERVER_PORT 2828 #endif /* CCAN_OSERVER_H */ diff --git a/ccan/oserver/oserver_types.h b/ccan/oserver/oserver_types.h index 8e99892..9943d09 100644 --- a/ccan/oserver/oserver_types.h +++ b/ccan/oserver/oserver_types.h @@ -42,5 +42,7 @@ CDUMP_SAVED struct oserver { int fd; struct tevent_fd *fde CDUMP_IGNORE; const char *dumpfile; + int argv_len; + char **argv CDUMP_LEN(argv_len); }; #endif /* CCAN_OSERVER_TYPES_H */ diff --git a/ccan/oserver/test/run-one-client-disconnect.c b/ccan/oserver/test/run-one-client-disconnect.c index 6023f78..f26c6ef 100644 --- a/ccan/oserver/test/run-one-client-disconnect.c +++ b/ccan/oserver/test/run-one-client-disconnect.c @@ -105,7 +105,7 @@ int main(int argc, char *argv[]) /* This is how many tests you plan to run */ plan_tests(2); - oserver = oserver_setup(ev, OSERVER_PORT, NULL); + oserver = oserver_setup(ev, OSERVER_PORT, NULL, NULL); if (!oserver) err(1, "Failed to set up server"); diff --git a/ccan/oserver/test/run.c b/ccan/oserver/test/run.c index a8eb6f2..0513e72 100644 --- a/ccan/oserver/test/run.c +++ b/ccan/oserver/test/run.c @@ -20,7 +20,7 @@ static void run_server(int readyfd, int exitfd) { struct tevent_context *ev = tevent_context_init(NULL); - if (oserver_setup(ev, OSERVER_PORT, NULL) == NULL) + if (oserver_setup(ev, OSERVER_PORT, NULL, NULL) == NULL) exit(1); tevent_add_fd(ev, ev, exitfd, TEVENT_FD_READ, exit_quietly, NULL); -- 2.39.2