Ver código fonte

[LibOS] Do not queue unmasked SIG_IGN'ed signals to prevent memory leak

When signal is unmasked and its handler is SIG_IGN, this signal must not
be queued, otherwise such queued but unused signals result in memory leak.
Additionally, SIGCHLD signal can be discarded even if it is unmasked. For
reference, see Linux code (do_notify_parent() @ linux/kernel/signal.c).
Isaku Yamahata 4 anos atrás
pai
commit
a9681fd20c
1 arquivos alterados com 15 adições e 1 exclusões
  1. 15 1
      LibOS/shim/src/bookkeep/shim_signal.c

+ 15 - 1
LibOS/shim/src/bookkeep/shim_signal.c

@@ -678,7 +678,8 @@ __handle_one_signal(shim_tcb_t* tcb, int sig, struct shim_signal* signal) {
 
 void __handle_signal (shim_tcb_t * tcb, int sig)
 {
-    struct shim_thread * thread = (struct shim_thread *) tcb->tp;
+    struct shim_thread * thread = tcb->tp;
+    assert(thread);
     int begin_sig = 1, end_sig = NUM_KNOWN_SIGS;
 
     if (sig)
@@ -735,6 +736,19 @@ void append_signal(struct shim_thread* thread, int sig, siginfo_t* info, bool ne
     if (!handler) {
         // SIGSTOP and SIGKILL cannot be ignored
         assert(sig != SIGSTOP && sig != SIGKILL);
+        /*
+         * If signal is ignored and unmasked, the signal can be discarded
+         * directly. Otherwise it causes memory leak.
+         *
+         * SIGCHLD can be discarded even if it's masked.
+         * For Linux implementation, please refer to
+         * do_notify_parent() in linux/kernel/signal.c
+         * For standard, please refer to
+         * https://pubs.opengroup.org/onlinepubs/9699919799/functions/_Exit.html
+         */
+        if (!__sigismember(&thread->signal_mask, sig) || sig == SIGCHLD)
+            return;
+
         // If a signal is set to be ignored, append the signal but don't interrupt the thread
         need_interrupt = false;
     }