summaryrefslogtreecommitdiff
path: root/Src/signals.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/signals.c')
-rw-r--r--Src/signals.c84
1 files changed, 78 insertions, 6 deletions
diff --git a/Src/signals.c b/Src/signals.c
index b1a843e2c..d28853ea6 100644
--- a/Src/signals.c
+++ b/Src/signals.c
@@ -31,10 +31,12 @@
#include "signals.pro"
/* Array describing the state of each signal: an element contains *
- * 0 for the default action or some ZSIG_* flags ored together. */
+ * 0 for the default action or some ZSIG_* flags ored together. *
+ * Contains TRAPCOUNT elements but can't be allocated statically *
+ * because that's a dynamic value on Linux */
/**/
-mod_export int sigtrapped[VSIGCOUNT];
+mod_export int *sigtrapped;
/*
* Trap programme lists for each signal.
@@ -48,7 +50,7 @@ mod_export int sigtrapped[VSIGCOUNT];
*/
/**/
-mod_export Eprog siglists[VSIGCOUNT];
+mod_export Eprog *siglists;
/* Total count of trapped signals */
@@ -892,7 +894,7 @@ dosavetrap(int sig, int level)
* Set a trap: note this does not handle manipulation of
* the function table for TRAPNAL functions.
*
- * sig is the signal number.
+ * sig is index into the table of trapped signals.
*
* l is the list to be eval'd for a trap defined with the "trap"
* builtin and should be NULL for a function trap.
@@ -931,6 +933,10 @@ settrap(int sig, Eprog l, int flags)
#endif
sig != SIGCHLD)
signal_ignore(sig);
+#if defined(SIGRTMIN) && defined(SIGRTMAX)
+ else if (sig >= VSIGCOUNT && sig < TRAPCOUNT)
+ signal_ignore(SIGNUM(sig));
+#endif
} else {
nsigtrapped++;
sigtrapped[sig] = ZSIG_TRAPPED;
@@ -940,6 +946,10 @@ settrap(int sig, Eprog l, int flags)
#endif
sig != SIGCHLD)
install_handler(sig);
+#if defined(SIGRTMIN) && defined(SIGRTMAX)
+ if (sig >= VSIGCOUNT && sig < TRAPCOUNT)
+ install_handler(SIGNUM(sig));
+#endif
}
sigtrapped[sig] |= flags;
/*
@@ -1019,6 +1029,11 @@ removetrap(int sig)
#endif
sig != SIGCHLD)
signal_default(sig);
+#if defined(SIGRTMIN) && defined(SIGRTMAX)
+ else if (sig >= VSIGCOUNT && sig < TRAPCOUNT)
+ signal_default(SIGNUM(sig));
+#endif
+
if (sig == SIGEXIT)
exit_trap_posix = 0;
@@ -1172,7 +1187,7 @@ endtrapscope(void)
static int
handletrap(int sig)
{
- if (!sigtrapped[sig])
+ if (!sigtrapped[SIGIDX(sig)])
return 0;
if (trap_queueing_enabled)
@@ -1189,7 +1204,7 @@ handletrap(int sig)
return 1;
}
- dotrap(sig);
+ dotrap(SIGIDX(sig));
if (sig == SIGALRM)
{
@@ -1481,3 +1496,60 @@ dotrap(int sig)
restore_queue_signals(q);
}
+
+#if defined(SIGRTMIN) && defined(SIGRTMAX)
+
+/* Realtime signals, these are a contiguous block that can
+ * be separated from the other signals with an unused gap. */
+
+/**/
+int
+rtsigno(const char* signame)
+{
+ const int maxofs = SIGRTMAX - SIGRTMIN;
+ const char *end = signame + 5;
+ int offset;
+ struct rtdir { int sig; int dir; char op; } x = { 0, 0, 0 };
+ if (!strncmp(signame, "RTMIN", 5)) {
+ x = (struct rtdir) { SIGRTMIN, 1, '+' };
+ } else if (!strncmp(signame, "RTMAX", 5)) {
+ x = (struct rtdir) { SIGRTMAX, -1, '-' };
+ } else
+ return 0;
+
+ if (signame[5] == x.op) {
+ if ((offset = strtol(signame + 6, (char **) &end, 10)) > maxofs)
+ return 0;
+ x.sig += offset * x.dir;
+ }
+ if (*end)
+ return 0;
+
+ return x.sig;
+}
+
+/**/
+char *
+rtsigname(int signo, int alt)
+{
+ char* buf = (char *) zhalloc(10);
+ int minofs = signo - SIGRTMIN;
+ int maxofs = SIGRTMAX - signo;
+ int offset;
+ int form = alt ^ (maxofs < minofs);
+
+ if (signo < SIGRTMIN || signo > SIGRTMAX)
+ return NULL;
+
+ strcpy(buf, "RT");
+ strcpy(buf+2, form ? "MAX-" : "MIN+");
+ offset = form ? maxofs : minofs;
+ if (offset) {
+ snprintf(buf + 6, 4, "%d", offset);
+ } else {
+ buf[5] = '\0';
+ }
+ return buf;
+}
+
+#endif