aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--TODO2
-rw-r--r--src/libmdsserver/macros.h10
-rw-r--r--src/mds-base.c51
-rw-r--r--src/mds-base.h12
-rw-r--r--src/mds-clipboard.c3
-rw-r--r--src/mds-echo.c3
-rw-r--r--src/mds-kkbd.c3
-rw-r--r--src/mds-registry/mds-registry.c3
-rw-r--r--src/mds-respawn.c3
-rw-r--r--src/mds-server/mds-server.c3
10 files changed, 82 insertions, 11 deletions
diff --git a/TODO b/TODO
index 5e009c3..1c8c7df 100644
--- a/TODO
+++ b/TODO
@@ -74,8 +74,6 @@ Register protocols
Make it possible to forbid unauthorised servers for listening, needed for secure password fields
I guess we can let servers create their own abstract sockets, report them to mdsinitrc and
let mdsinitrc export appropriate environment variables.
-Signals that should be supported, and be replaced with realtime signals if not defined:
- SIGDANGER system or process is running out of memory
A facility is needed to lookup available compose sequences to any character,
it would be useful in character map programs so one can easier learn the
compose sequences for character that one uses often
diff --git a/src/libmdsserver/macros.h b/src/libmdsserver/macros.h
index 2d3f7a3..215c51a 100644
--- a/src/libmdsserver/macros.h
+++ b/src/libmdsserver/macros.h
@@ -24,6 +24,7 @@
#include <stdio.h>
#include <errno.h>
+#include <signal.h>
/*
#include <unistd.h>
@@ -363,5 +364,14 @@
#define exit_if(CONDITION, INSTRUCTIONS) if (CONDITION) { INSTRUCTIONS return 1; }
+/**
+ * The system is running out of memory.
+ * Quick, free up all your unused memory or kill yourself!
+ */
+#ifndef SIGDANGER
+# define SIGDANGER SIGRTMAX
+#endif
+
+
#endif
diff --git a/src/mds-base.c b/src/mds-base.c
index be4efbb..429632e 100644
--- a/src/mds-base.c
+++ b/src/mds-base.c
@@ -192,8 +192,9 @@ int __attribute__((weak)) connect_to_display(void)
*/
static int server_initialised_fork_for_safety(void)
{
- unsigned pending_alarm = alarm(0);
+ unsigned pending_alarm = alarm(0); /* Disable the alarm. */
pid_t pid = fork();
+ int status;
if (pid == (pid_t)-1)
{
@@ -202,17 +203,29 @@ static int server_initialised_fork_for_safety(void)
return -1;
}
else if (pid == 0)
+ /* Reinstate the alarm for the child. */
alarm(pending_alarm);
else
{
- int status;
+ /* SIGDANGER cannot hurt the parent process. */
+ if (xsigaction(SIGDANGER, SIG_IGN) < 0)
+ {
+ xperror(*argv);
+ eprint("WARNING! parent process failed to sig up ignoring of SIGDANGER.");
+ }
+
+ /* Wait for the child process to die. */
if (uninterruptable_waitpid(pid, &status, 0) == (pid_t)-1)
{
xperror(*argv);
kill(pid, SIGABRT);
sleep(5);
}
+
+ /* Clean up after us. */
fork_cleanup(status);
+
+ /* Die like the child. */
if (WIFEXITED(status)) exit(WEXITSTATUS(status));
else if (WIFSIGNALED(status)) raise(WTERMSIG(status));
exit(1);
@@ -541,6 +554,32 @@ int main(int argc_, char** argv_)
/**
+ * This function is called when `SIGDANGER` is received
+ * of `server_characteristics.danger_is_deadly` is non-zero
+ * unless the signal handler for `SIGDANGER` has been
+ * modified by the server implementation.
+ *
+ * This function will abruptly kill the process
+ *
+ * @param signo The signal that has been received
+ */
+static void commit_suicide(int signo)
+{
+ (void) signo;
+
+ eprint("SIGDANGER received, process is killing itself to free memory.");
+
+ /* abort(), but on the process rather than the thread. */
+ xsigaction(SIGABRT, SIG_DFL);
+ kill(getpid(), SIGABRT);
+
+ /* Just in case. */
+ xperror(*argv);
+ _exit(1);
+}
+
+
+/**
* Set up signal traps for all especially handled signals
*
* @return Non-zero on error
@@ -556,9 +595,15 @@ int trap_signals(void)
/* Implement clean exit on SIGINT. */
fail_if (xsigaction(SIGINT, received_terminate) < 0);
- /* Implement clean exit on SIGRTMIN. */
+ /* Implement silent interruption on SIGRTMIN. */
fail_if (xsigaction(SIGRTMIN, received_noop) < 0);
+ /* Implement silent interruption on SIGDANGER. */
+ if (server_characteristics.danger_is_deadly)
+ { fail_if (xsigaction(SIGDANGER, commit_suicide) < 0); }
+ else
+ { fail_if (xsigaction(SIGDANGER, SIG_IGN) < 0); }
+
return 0;
pfail:
xperror(*argv);
diff --git a/src/mds-base.h b/src/mds-base.h
index 2dac449..c3c6c9c 100644
--- a/src/mds-base.h
+++ b/src/mds-base.h
@@ -64,6 +64,18 @@ typedef struct server_characteristics
*/
unsigned fork_for_safety : 1;
+ /**
+ * Seting this to non-zero without setting a signal action
+ * for `SIGDANGER` will cause the server to die if `SIGDANGER`
+ * is received. It is safe to set both `danger_is_deadly` and
+ * `fork_for_safety` to non-zero, during the call of
+ * `server_initialised` the signal handler for `SIGDANGER`
+ * in the parent process will be set to `SIG_IGN` independently
+ * of the value of `danger_is_deadly` if `fork_for_safety`
+ * is set to non-zero.
+ */
+ unsigned danger_is_deadly : 1;
+
} __attribute__((packed)) server_characteristics_t;
diff --git a/src/mds-clipboard.c b/src/mds-clipboard.c
index 7ed2508..6ad068b 100644
--- a/src/mds-clipboard.c
+++ b/src/mds-clipboard.c
@@ -46,7 +46,8 @@ server_characteristics_t server_characteristics =
.require_display = 1,
.require_respawn_info = 1,
.sanity_check_argc = 1,
- .fork_for_safety = 0
+ .fork_for_safety = 0,
+ .danger_is_deadly = 0
};
diff --git a/src/mds-echo.c b/src/mds-echo.c
index 01f8e97..2b20387 100644
--- a/src/mds-echo.c
+++ b/src/mds-echo.c
@@ -46,7 +46,8 @@ server_characteristics_t server_characteristics =
.require_display = 1,
.require_respawn_info = 0,
.sanity_check_argc = 1,
- .fork_for_safety = 0
+ .fork_for_safety = 0,
+ .danger_is_deadly = 0
};
diff --git a/src/mds-kkbd.c b/src/mds-kkbd.c
index 11d33b1..db12746 100644
--- a/src/mds-kkbd.c
+++ b/src/mds-kkbd.c
@@ -88,7 +88,8 @@ server_characteristics_t server_characteristics =
.require_display = 1,
.require_respawn_info = 0,
.sanity_check_argc = 1,
- .fork_for_safety = 1
+ .fork_for_safety = 1,
+ .danger_is_deadly = 0
};
diff --git a/src/mds-registry/mds-registry.c b/src/mds-registry/mds-registry.c
index baefee7..1676cf6 100644
--- a/src/mds-registry/mds-registry.c
+++ b/src/mds-registry/mds-registry.c
@@ -43,7 +43,8 @@ server_characteristics_t server_characteristics =
.require_display = 1,
.require_respawn_info = 0,
.sanity_check_argc = 1,
- .fork_for_safety = 0
+ .fork_for_safety = 0,
+ .danger_is_deadly = 0
};
diff --git a/src/mds-respawn.c b/src/mds-respawn.c
index 02b466c..6072ad9 100644
--- a/src/mds-respawn.c
+++ b/src/mds-respawn.c
@@ -47,7 +47,8 @@ server_characteristics_t server_characteristics =
.require_display = 0,
.require_respawn_info = 1,
.sanity_check_argc = 0,
- .fork_for_safety = 0
+ .fork_for_safety = 0,
+ .danger_is_deadly = 0
};
diff --git a/src/mds-server/mds-server.c b/src/mds-server/mds-server.c
index 85e7c5c..a77fadb 100644
--- a/src/mds-server/mds-server.c
+++ b/src/mds-server/mds-server.c
@@ -57,7 +57,8 @@ server_characteristics_t server_characteristics =
.require_display = 0, /* We will service one ourself. */
.require_respawn_info = 1,
.sanity_check_argc = 1,
- .fork_for_safety = 0
+ .fork_for_safety = 0,
+ .danger_is_deadly = 0
};