aboutsummaryrefslogtreecommitdiffstats
path: root/src/mds-base.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mds-base.c')
-rw-r--r--src/mds-base.c68
1 files changed, 66 insertions, 2 deletions
diff --git a/src/mds-base.c b/src/mds-base.c
index 77b8835..1bae36b 100644
--- a/src/mds-base.c
+++ b/src/mds-base.c
@@ -182,12 +182,54 @@ int __attribute__((weak)) connect_to_display(void)
return 1;
}
+
+/**
+ * Put the server into a fork of itself as
+ * described by the `fork_for_safety`
+ * server characteristics
+ *
+ * @return Zero on success, -1 on error
+ */
+static int server_initialised_fork_for_safety(void)
+{
+ unsigned pending_alarm = alarm(0);
+ pid_t pid = fork();
+
+ if (pid == (pid_t)-1)
+ {
+ xperror(*argv);
+ eprint("while forking for safety.");
+ return -1;
+ }
+ else if (pid == 0)
+ alarm(pending_alarm);
+ else
+ {
+ int status;
+ if (uninterruptable_waitpid(pid, &status, 0) == (pid_t)-1)
+ {
+ xperror(*argv);
+ kill(pid, SIGABRT);
+ sleep(5);
+ }
+ fork_cleanup(status);
+ if (WIFEXITED(status)) exit(WEXITSTATUS(status));
+ else if (WIFSIGNALED(status)) raise(WTERMSIG(status));
+ exit(1);
+ }
+
+ return 0;
+}
+
+
/**
* This function should be called when the server has
* been properly initialised but before initialisation
* of anything that is removed at forking is initialised
+ *
+ * @return Zero on success, -1 on error
*/
-void __attribute__((weak)) server_initialised(void)
+int __attribute__((weak)) server_initialised(void)
{
pid_t r;
if (on_init_fork && (r = fork()))
@@ -196,7 +238,7 @@ void __attribute__((weak)) server_initialised(void)
{
xperror(*argv);
eprint("while forking at completed initialisation.");
- exit(1);
+ return -1;
}
else
exit(0);
@@ -204,6 +246,10 @@ void __attribute__((weak)) server_initialised(void)
if (on_init_sh != NULL)
system(on_init_sh);
+
+ if (server_characteristics.fork_for_safety)
+ return server_initialised_fork_for_safety();
+ return 0;
}
@@ -495,5 +541,23 @@ int trap_signals(void)
}
+/**
+ * This function should be implemented by the actual server implementation
+ * if the server has set `server_characteristics.fork_for_safety` to be
+ * true
+ *
+ * This function is called by the parent server process when the
+ * child server process exits, if the server has completed its
+ * initialisation
+ *
+ * @param status The status the child died with
+ */
+void __attribute__((weak)) fork_cleanup(int status)
+{
+ (void) status;
+ fprintf(stderr, "Something is wrong, `fork_cleanup` has been called but not reimplemented.");
+}
+
+
#undef try