diff options
author | Mattias Andrée <maandree@kth.se> | 2016-07-12 10:42:29 +0200 |
---|---|---|
committer | Mattias Andrée <maandree@kth.se> | 2016-07-12 10:42:52 +0200 |
commit | d7cf13b968b99cb070c7d5d2e1f7ff1a8072f2f3 (patch) | |
tree | 89b172602b2d5dd2ebeb7450a5247614b9d04d00 /src/gammad.c | |
parent | Implement state merging (diff) | |
download | coopgammad-d7cf13b968b99cb070c7d5d2e1f7ff1a8072f2f3.tar.gz coopgammad-d7cf13b968b99cb070c7d5d2e1f7ff1a8072f2f3.tar.bz2 coopgammad-d7cf13b968b99cb070c7d5d2e1f7ff1a8072f2f3.tar.xz |
Implement re-exec
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to '')
-rw-r--r-- | src/gammad.c | 53 |
1 files changed, 52 insertions, 1 deletions
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: |