From d7cf13b968b99cb070c7d5d2e1f7ff1a8072f2f3 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Tue, 12 Jul 2016 10:42:29 +0200 Subject: Implement re-exec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- src/gammad.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) (limited to 'src/gammad.c') diff --git a/src/gammad.c b/src/gammad.c index 254dd52..fa24d82 100644 --- a/src/gammad.c +++ b/src/gammad.c @@ -1210,7 +1210,8 @@ static void usage(void) int main(int argc, char** argv) { int rc = 1, preserve = 0, foreground = 0, keep_stderr = 0, r; - const char* statefile = NULL; + char* statefile = NULL; + char* statebuffer = NULL; ARGBEGIN { @@ -1245,6 +1246,8 @@ int main(int argc, char** argv) if (argc > 0) usage(); + restart: /* If C had comefrom: comefrom reexec_failure; */ + switch ((r = initialise(statefile == NULL, preserve, foreground, keep_stderr))) { case 1: @@ -1265,12 +1268,60 @@ int main(int argc, char** argv) if (unmarshal_and_merge_state(statefile) < 0) goto fail; unlink(statefile), statefile = NULL; + reexec = 0; /* See `if (reexec && !terminate)` */ + } + + if (reexec && !terminate) + { + size_t buffer_size; + int fd; + + /* `reexec = 0;` is done later in case of re-execute failure, + * since it determines whether `statefile` shall be freed. */ + + statefile = get_state_pathname(); + if (statefile == NULL) + goto fail; + + buffer_size = marshal(NULL); + statebuffer = malloc(buffer_size); + if (statebuffer == NULL) + goto fail; + if (marshal(statebuffer) != buffer_size) + abort(); + + fd = open(statefile, O_CREAT, S_IRUSR | S_IWUSR); + if (fd < 0) + goto fail; + + if (nwrite(fd, statebuffer, buffer_size) != buffer_size) + { + perror(argv0); + close(fd); + errno = 0; + goto fail; + } + free(statebuffer), statebuffer = NULL; + + if ((close(fd) < 0) && (errno != EINTR)) + goto fail; + + destroy(0); + + execlp(argv0_real ? argv0_real : argv0, argv0, "-#", statefile, preserve ? "-p" : NULL, NULL); + perror(argv0); + fprintf(stderr, "%s: restoring state without re-executing\n", argv0); + free(argv0_real), argv0_real = NULL; + goto restart; } rc = 0; done: + free(statebuffer); if (statefile) unlink(statefile); + if (reexec) + free(statefile); destroy(1); return rc; fail: -- cgit v1.2.3-70-g09d2