From: Alan Cox Date: Mon, 2 Apr 2018 22:01:15 +0000 (+0100) Subject: signals: fix signal leak by pushing back a pending signal when we recalc X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=f8a13d22ec4ffe63845f2359cd7b501893144d27;p=FUZIX.git signals: fix signal leak by pushing back a pending signal when we recalc --- diff --git a/Kernel/include/kernel.h b/Kernel/include/kernel.h index 889a6c0a..ec54b02f 100644 --- a/Kernel/include/kernel.h +++ b/Kernel/include/kernel.h @@ -920,6 +920,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 recalc_cursig(void); extern uint8_t chksigs(void); extern void program_vectors(uint16_t *pageptr); extern void sgrpsig(uint16_t pgrp, uint8_t sig); diff --git a/Kernel/process.c b/Kernel/process.c index 6728bed6..051f5d78 100644 --- a/Kernel/process.c +++ b/Kernel/process.c @@ -550,8 +550,22 @@ static const uint16_t clear = SIGBIT(SIGCHLD) | SIGBIT(SIGURG) | SIGBIT(SIGWINCH) | SIGBIT(SIGIO) | SIGBIT(SIGCONT); -/* Process a block of 16 signals so we can avoid using longs */ +/* Put back a computed signal so that we can recalculate what needs to be + serviced correctly */ +void recalc_cursig(void) +{ + if (udata.u_cursig) { + struct sigbits *sb = udata.u_ptab->p_sig; + if (udata.u_cursig & 16) { + sb++; + udata.u_cursig &= ~16; + } + sb->s_pending |= 1 << udata.u_cursig; + udata.u_cursig = 0; + } +} +/* Process a block of 16 signals so we can avoid using longs */ static uint8_t chksigset(struct sigbits *sb, uint8_t b) { uint8_t j = 1; @@ -641,8 +655,10 @@ uint8_t chksigs(void) /* Sleeping without signals allowed. We rely upon the fact that P_IOWAIT is never pre-empted or returns to user space so udata.u_cursig is not consulted until it is safe to do so */ - if (udata.u_ptab->p_status == P_IOWAIT) + if (udata.u_ptab->p_status == P_IOWAIT) { + recalc_cursig(); return 0; + } /* Fast path - no signals pending means no work. Cursig being set means we've already worked out what to do. diff --git a/Kernel/syscall_proc.c b/Kernel/syscall_proc.c index 441fb575..de246491 100644 --- a/Kernel/syscall_proc.c +++ b/Kernel/syscall_proc.c @@ -479,7 +479,7 @@ arg_t _signal(void) if (sig != SIGKILL && sig != SIGSTOP) udata.u_sigvec[sig] = func; /* Force recalculation of signal pending in the syscall return path */ - udata.u_cursig = 0; + recalc_cursig();; irqrestore(irq); return (retval); @@ -514,7 +514,7 @@ arg_t _sigdisp(void) else sb->s_held &= ~sigmask(sig); /* Force recalculation of signal pending in the syscall return path */ - udata.u_cursig = 0; + recalc_cursig(); return 0; }