[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[tyndur-devel] [PATCH 4/5] libc: POSIX: Mehr Signale



+ libc: POSIX: Signale blockieren mit sigprocmask()
! libc: POSIX: raise() setzt errno, wenn es -1 zurueckgibt
---
 src/modules/include/signal.h   |   20 +++++++++++++-
 src/modules/lib/posix/signal.c |   59 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 78 insertions(+), 1 deletions(-)

diff --git a/src/modules/include/signal.h b/src/modules/include/signal.h
index 364cd67..ab67d88 100644
--- a/src/modules/include/signal.h
+++ b/src/modules/include/signal.h
@@ -146,6 +146,12 @@ struct sigaction {
     int             sa_flags;
 };
 
+enum {
+    SIG_BLOCK,
+    SIG_UNBLOCK,
+    SIG_SETMASK,
+};
+
 
 /**
  * Aendert die auszufuehrende Aktion fuer ein Signal und gibt die alte Aktion
@@ -158,9 +164,21 @@ struct sigaction {
  */
 int sigaction(int sig, const struct sigaction* action, struct sigaction* old);
 
-/// Einen Signal-Hander aendern
+/// Einen Signal-Handler aendern
 sighandler_t signal(int signum, sighandler_t handler);
 
+/**
+ * Verwaltung von blockierten Signalen
+ *
+ * @param mode SIG_BLOCK: Alle Signale aus sigset blockieren
+ * SIG_UNBLOCK: Alle Signale aus sigset wieder aktivieren
+ * SIG_SETMASK: sigset als neue Signal-Maske benutzen
+ *
+ * @return 0 bei Erfolg. -1 und errno = EINVAL, wenn mode einen unerlaubten
+ * Wert hat.
+ */
+int sigprocmask(int mode, const sigset_t* sigset, sigset_t* oldset);
+
 /// Ein Signal zum aktuellen Prozess senden
 int raise(int signal);
 
diff --git a/src/modules/lib/posix/signal.c b/src/modules/lib/posix/signal.c
index 03cfb56..e35064d 100644
--- a/src/modules/lib/posix/signal.c
+++ b/src/modules/lib/posix/signal.c
@@ -38,6 +38,7 @@
 
 /// Array mit Pointern auf die Signal-Handler
 static struct sigaction sigactions[_SIGNO_MAX];
+static sigset_t sigmask;
 static bool initialized = FALSE;
 
 /**
@@ -46,7 +47,10 @@ static bool initialized = FALSE;
 static void init_signals(void)
 {
     int i;
+
     memset(sigactions, 0, sizeof(sigactions));
+    memset(&sigmask, 0, sizeof(sigmask));
+
     for (i = 0; i < _SIGNO_MAX; i++) {
         sigactions[i].sa_handler = SIG_DFL;
     }
@@ -71,9 +75,16 @@ int raise(int signum)
     // Wenn das Signal Groesser ist als die Groesste gueltige wird sofort
     // abgebrochen.
     if (signum >= _SIGNO_MAX) {
+        errno = EINVAL;
         return -1;
     }
 
+    // Pruefen, ob das Signal nicht blockiert ist
+    if (sigismember(&sigmask, signum)) {
+        return 0;
+    }
+
+    // Handler aufrufen
     sighandler_t handler = sigactions[signum].sa_handler;
     if (handler != NULL) {
         handler(signum);
@@ -290,6 +301,54 @@ int sigismember(const sigset_t *sigset, int signum)
 }
 
 /**
+ * Verwaltung von blockierten Signalen
+ *
+ * @param mode SIG_BLOCK: Alle Signale aus sigset blockieren
+ * SIG_UNBLOCK: Alle Signale aus sigset wieder aktivieren
+ * SIG_SETMASK: sigset als neue Signal-Maske benutzen
+ *
+ * @return 0 bei Erfolg. -1 und errno = EINVAL, wenn mode einen unerlaubten
+ * Wert hat.
+ */
+int sigprocmask(int mode, const sigset_t* sigset, sigset_t* oldset)
+{
+    int i;
+
+    if (oldset != NULL) {
+        memcpy(oldset, &sigmask, sizeof(sigset_t));
+    }
+
+    switch (mode) {
+        case SIG_BLOCK:
+            for (i = 0; i < _SIGNO_MAX; i++) {
+                if (sigismember(sigset, i)) {
+                    sigaddset(&sigmask, i);
+                }
+            }
+            break;
+
+        case SIG_UNBLOCK:
+            for (i = 0; i < _SIGNO_MAX; i++) {
+                if (sigismember(sigset, i)) {
+                    sigdelset(&sigmask, i);
+                }
+            }
+            break;
+
+        case SIG_SETMASK:
+            memcpy(&sigmask, sigset, sizeof(sigset_t));
+            break;
+
+        default:
+            errno = EINVAL;
+            return -1;
+    }
+
+    return 0;
+}
+
+
+/**
  * Callbackfunktion fuer alarm()
  */
 static void do_alarm(void)
-- 
1.6.0.2