signal: fix handling of pending signals whose default behaviour is ignore
authorAlan Cox <alan@linux.intel.com>
Sun, 28 Aug 2016 22:45:29 +0000 (23:45 +0100)
committerAlan Cox <alan@linux.intel.com>
Sun, 28 Aug 2016 22:45:29 +0000 (23:45 +0100)
Also noted by David Flamand.

We make chksigs() a generally callable helper so that anyone who needs to
check if a signal is pending can just ask it. This cleans up the (broken)
poking around we were doing as well.

This also cleans up some other freaky corner cases where signals delivered
at the wrong time could be lost.

Kernel/devio.c
Kernel/include/kernel.h
Kernel/process.c

index e7dd531..77d7371 100644 (file)
@@ -480,7 +480,7 @@ int psleep_flags_io(void *p, unsigned char flags, usize_t *n)
                return -1;
        }
        psleep(p);
-       if (udata.u_cursig || udata.u_ptab->p_pending) {        /* messy */
+       if (chksigs()) {
                if (!*n) {
                        *n = (usize_t)-1;
                         udata.u_error = EINTR;
index 01e5e00..3ecf6ea 100644 (file)
@@ -828,7 +828,7 @@ extern ptptr getproc(void);
 extern void newproc(ptptr p);
 extern ptptr ptab_alloc(void);
 extern void ssig(ptptr proc, uint8_t sig);
-extern void chksigs(void);
+extern uint8_t chksigs(void);
 extern void program_vectors(uint16_t *pageptr);
 extern void sgrpsig(uint16_t pgrp, uint8_t sig);
 extern void unix_syscall(void);
index 819a65e..a5c0053 100644 (file)
@@ -448,18 +448,19 @@ static uint8_t dump_core(uint8_t sig)
 
 /* This sees if the current process has any signals set, and handles them.
  */
-void chksigs(void)
+uint8_t chksigs(void)
 {
        uint8_t j;
        uint32_t pending = udata.u_ptab->p_pending & ~udata.u_ptab->p_held;
        int (**svec)(int) = &udata.u_sigvec[0];
        uint32_t m;
 
-       /* Fast path - no signals pending means no work
+       /* Fast path - no signals pending means no work.
+          Cursig being set means we've already worked out what to do.
           Also don't do signal processing if we are in P_STOPPED. This
           isn't quite right but will paper over the holes for the moment
           FIXME */
-       if (!pending || udata.u_ptab->p_status == P_STOPPED)
+       if (udata.u_cursig || !pending || udata.u_ptab->p_status == P_STOPPED)
                return;
 
        /* Dispatch the lowest numbered signal */
@@ -504,6 +505,7 @@ void chksigs(void)
                        break;
                }
        }
+       return udata.u_cursig;
 }
 
 /*