aboutsummaryrefslogtreecommitdiffstats
path: root/src/gammad.c
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2016-07-12 10:42:29 +0200
committerMattias Andrée <maandree@kth.se>2016-07-12 10:42:52 +0200
commitd7cf13b968b99cb070c7d5d2e1f7ff1a8072f2f3 (patch)
tree89b172602b2d5dd2ebeb7450a5247614b9d04d00 /src/gammad.c
parentImplement state merging (diff)
downloadcoopgammad-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 'src/gammad.c')
-rw-r--r--src/gammad.c53
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: