It seems that we all are just trying to confuse each other. I got lost. On 05/23, David Laight wrote: > > From: Oleg Nesterov > > Sent: 23 May 2019 17:36 > > On 05/23, David Laight wrote: > > > > > > From: Oleg Nesterov > > > > On 05/23, David Laight wrote: > ... > > > > Not sure I understand... OK, suppose that you do > > > > > > > > block-all-signals; > > > > ret = pselect(..., sigmask(SIG_URG)); > > > > > > > > if it returns success/timeout then the handler for SIG_URG should not > > > > be called? > > > > > > Ugg... > > > Posix probably allows the signal handler be called at the point the event > > > happens rather than being deferred until the system call completes. > > > Queueing up the signal handler to be run at a later time (syscall exit) > > > certainly makes sense. > > > Definitely safest to call the signal handler even if success/timeout > > > is returned. > > > > Why? > > > > > pselect() exists to stop the entry race, not the exit one. > > > > pselect() has to block SIG_URG again before it returns to user-mode, right? > > Yep. > So the signal handler can't be called for a signal that happens after > pselect() returns.
Yes. And "after pselect() returns" actually means "after pselect() restores the old sigmask while it returns to user mode". > > Suppose pselect() finds a ready fd, and this races with SIG_URG. > > You mean if SIG_URG is raised after a ready fd is found (or even timeout)? > So the return value isn't EINTR. Yes. > (If an fd is readable on entry, the SIG_URG could have happened much earlier.) Why not? See the pseudo code above. It was blocked before pselect() was called. So SIG_URG can be already pending when pselect() is called but since an fd is already ready on entry pselect() restores the old sigmask (and thus blocks SIG_URG again) and returns success. The handler is not called. However, if there is no a ready fd, pselect won't block. It will notice SIG_URG, deliver this signal, and return -EINTR. > > Why do you think the handler should run? > > Think of the application code loop. > Consider what happens if the signal is SIG_INT - to request the program > stop. SIG_INT or SIG_URG ? Again, please look at the pseudo code above. SIG_INT is blocked and never unblocked. > After every pselect() call the application looks to see if the handler > has been called. > If one of the fds is always readable pselect() will never return EINTR > but you want the SIG_INT handler run so that the loop gets terminated. > If you only call the signal handler when EINTR is returned the process > will never stop. > So you need to call the handler even when pselect() succeeds/time out. Then do not block SIG_INT ? block-all-signals-except-SIG_INT; ret = pselect(..., sigmask{SIG_URG, SIG_INT}); > > What if SIG_URG comes right after pselect() blocks SIG_URG again? I mean, > > how this differs the case when it comes before, but a ready fd was already > > found? > > I suspect you need to defer the re-instatement of the original mask > to the code that calls the signal handlers (which probably should > be called with the programs signal mask). This is what the kernel does when the signal is delivered, the original mask is restored after the signal handler runs. > So that particular window doesn't exist. Which window??? Oleg.