A NOTE has been added to this issue. ====================================================================== https://austingroupbugs.net/view.php?id=1731 ====================================================================== Reported By: geoffclare Assigned To: ====================================================================== Project: 1003.1(2016/18)/Issue7+TC2 Issue ID: 1731 Category: System Interfaces Type: Clarification Requested Severity: Objection Priority: normal Status: New Name: Geoff Clare Organization: The Open Group User Reference: Section: pthread_sigmask() Page Number: 1734 Line Number: 56243 Interp Status: --- Final Accepted Text: ====================================================================== Date Submitted: 2023-05-23 09:43 UTC Last Modified: 2023-06-06 19:24 UTC ====================================================================== Summary: pthread_sigmask() pending signal requirement time paradox ======================================================================
---------------------------------------------------------------------- (0006313) kre (reporter) - 2023-06-06 19:24 https://austingroupbugs.net/view.php?id=1731#c6313 ---------------------------------------------------------------------- Re https://austingroupbugs.net/view.php?id=1731#c6312 First, I am not proposing any requirement, just to leave the requirement in this function the same as it has always been, your change was to add a new requirement (that the signal delivered be one that was just unblocked, rather than simply any pending deliverable signal). If my wording seemed to be adding something new, then use some other wording which does not. I certainly did not intend to alter anything, except to avoid the before/after issue. I see nothing in the description of the Illuminos code that you included (I am one of those "some people" though I have no idea what kind of licence Illuminos has on its code) which is different in any material way from the BSD code fragments I posted (BSD code these days is licensed mostly with a "don't sue anyone" type licence, if it matters to anyone). This doesn't mean there isn't one - just that your note did not mention it. The t_sig_check field looks like a different (and perhaps better) optimisation than what the CURSIG() macro in BSD provides; as you describe it, it merely encompasses the idea that there cannot be a signal pending unless someone has delivered one (or unblocked one) - and hence it is pointless to test whether one might now be pending (whereas the BSD code tests every time, but tries to make that test as cheap as possible). [ While it seems "obvious" it is a better way, it isn't necessarily - setting the field needs to be protected by a lock to guard against it simultaneously being cleared - that might be more costly than is warranted - or might be zero if the relevant code is already running holding a suitable lock for the purpose. And that is an extra field which makes the structure bigger, which also has costs - on fork, there is more to copy, for example, and more memory is consumed. So, this way might be improvement, or might not be, much benchmarking would be required for a definitive answer - and that might vary from system to system. ] t_sig_check doesn't need to be set in the SIG_BLOCK case, as that cannot be allowing any signals that were pending to be delivered, and it is not sending a signal of its own. I would assume that all code which sends a signal, in addition to that code which unblocks pending signals, sets t_sig_check. Check their code for the kill() system call and verify that also sets that field (on the process/thread being sent the signal of course, not the one sending it, unless they are the same), and if you feel inclined, the code that sends SIGCHLD when a child exits, which should do the same (if the signal is actually sent. or SIGALRM if a timer expires). Traps which send signals should do the same - though one of those should not normally happen to a process running inside a system call. Nothing you described has any bearing upon what signal gets delivered to the process when the sigprocmask() system all is done - whether it is one that was just unblocked, or another that happened to arrive while that system call was running. You would need to look deeper into what the post_syscall() function you mention does in that case that t_sig_check is set, to discover if it somehow makes a distinction between a signal that has been pending, and is now unblocked, and one which was never blocked, but just arrived while the system call was running (a child exiting that was running on a different CPU would, I suspect, be the most likely way that might happen - but since this is a very fast system call (only likely to block if it needs to wait on some internal data structure lock, or if is pre-empted) the chances of that happening are very small. Since you (seem to) want to change the requirement from what it has been, I'd expect it is incumbent upon you to show that at least most systems behave the way that you believe they should behave. I actually doubt that there are any - but that's just based upon the way the code was developed, and intuition, not investigation. The requirement that if a pending signal was unblocked, that it be delivered before the system call returns (which in reality means before any other application code runs after the system call returns - though it will be before the library function that made the system call returns) doesn't really need to be there at all - if there is a pending signal when any system call completes, that signal (or one of them if there is more than one) is taken before the application runs any more code (for all system calls). I suspect that the requirement is there just to make it clear that unblocking a pending signal is equivalent to sending that signal, and implementations aren't permitted to only deliver signals if the system call being run actually generated one, which is probably reasonable (someone implementing an OS from the standard, without any experience, could make that mistake). I'd suggest simply fixing the time paradox, and avoid attempting to "fix" the wording otherwise than that, as what is there now, is almost certainly exactly what it should say (things occurring after things they precede excepted, of course). Alternatively, we could just leave the time paradox there as a "quaint oddity" as it doesn't really affect anything (but no, I am not suggesting doing that, just that that would be better than the proposed change). While (re-)considering the change you are proposing, consider this case. Let's assume that SIGINT SIGQUIT and SIGTSTP are blocked, and there is a pending SIGINT waiting to be delivered, but neither of the others. The application calls pthread_sigmask() to unblock those 3 signals. In the normal course of events, the SIGINT would be delivered to the application as soon as it starts to run again - before the pthread_sigmask() call returns, and that is what you are trying to say is required. But let's assume that before the application gets put back on a CPU to run (perhaps its priority has degraded, and higher priority processes are now running on all CPUs that are available) the user types the terminal's stop character (usually ^Z) which the terminal driver turns into a progress group SIGTSTP to the process group of the terminal - one member of which, we will assume, is our application. Are you contending that the system may not deliver that SIGTSTP (instead of the SIGINT) if it so desires? Because that is what the wording you proposed would suggest. The SIGTSTP signal was not a pending signal which became unblocked by the pthread_sigmask() call, it had not occurred yet when the unblocking happened, hence it is not the case that "the change made to the currently blocked set of signals causes any pending signals to become unblocked," for that signal, but it was for SIGINT, so according to your wording, only the SIGINT can be delivered, and not the SIGTSTP. The previous (current) wording simply says that if there are any unblocked signals when the call returns (which there are now, 2 of them, SIGINT and SIGTSTP) then one of them must be delivered immediately - it does not say which, and nor should it. Issue History Date Modified Username Field Change ====================================================================== 2023-05-23 09:43 geoffclare New Issue 2023-05-23 09:43 geoffclare Name => Geoff Clare 2023-05-23 09:43 geoffclare Organization => The Open Group 2023-05-23 09:43 geoffclare Section => pthread_sigmask() 2023-05-23 09:43 geoffclare Page Number => 1734 2023-05-23 09:43 geoffclare Line Number => 56243 2023-05-23 09:43 geoffclare Interp Status => --- 2023-05-23 21:08 kre Note Added: 0006287 2023-05-25 08:40 geoffclare Note Added: 0006288 2023-05-25 18:26 kre Note Added: 0006292 2023-05-25 18:32 kre Note Edited: 0006292 2023-05-25 18:44 kre Note Added: 0006293 2023-05-30 11:14 geoffclare Note Added: 0006294 2023-05-31 19:50 kre Note Added: 0006296 2023-06-06 15:50 geoffclare Note Added: 0006312 2023-06-06 19:24 kre Note Added: 0006313 ======================================================================
