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-09 11:24 UTC ====================================================================== Summary: pthread_sigmask() pending signal requirement time paradox ======================================================================
---------------------------------------------------------------------- (0006316) kre (reporter) - 2023-06-09 11:24 https://austingroupbugs.net/view.php?id=1731#c6316 ---------------------------------------------------------------------- Re https://austingroupbugs.net/view.php?id=1731#c6314 First, I don't think I've ever had a problem with the suggestions I have made for wording being improved, in fact, I usually expect that, as wordsmithing isn't really my thing - and certainly if anything I have suggested adds some unwanted requirement, that should certainly be removed. In this case, I don't see much real difference between what is in the standard now, and my suggestion (except the time paradox is gone), but as we're trying to improve that language, by all means, improve it. However wrt: Extrapolating, it effectively would require that all pending unblocked signals are delivered before pthread_sigmask() returns. That's actually what happens, in most systems anyway, though the mechanism (and precise details of how) may tend to vary. In general an application should never be running user code with a pending unblocked signal. Any signals that arrive should be processed (either cause the process to exit, or call an application signal handler (or do nothing of course)) as soon as possible. That means now (when the signal is generated) for signals that are not blocked, or as soon as the signal is unblocked for those which are. In the case of the example, when there are two pending signals when a system call returns, typically implementations behave in one of two ways. First they pick a signal that is pending to deliver (this is usually done in a deterministic way, but need not be) and set up the application state to reflect the first instruction of the user's handler routine is the next to execute, and the return address is that of the current location in the pthread_setmask() routine (immediately after the system call invoking instruction, or however the architecture makes that happen). Part of that process is applying the mask from the struct sigaction for the signal to the current signal mask - once that's done there might be no more pending unblocked signals, control returns to the application, and the handler is executed. When it completes, it notifies the system it has done so, any signals that were blocked by its sigaction become unblocked, and if there now are any pending unblocked signals, the whole process repeats, with the next pending signal (which at this stage could even be the same one for which the handler was just invoked - which can happen if the handler changes the disposition of the signal (usually) and then raises the signal again). In the case that the handler's mask did not block all the signals, and another signal remained pending and unblocked, then before resuming user mode, that signal is usually taken - which will result in things appearing to the application, if it were to look, as if the handler for the first signal invoked was interrupted immediately by the second signal - the handler for the second signal delivered runs first, then when it completes, the handler for the first signal is still waiting to executed. That might look like a strange thing to have happen, but is really no different than if the handler for the first signal selected had just started running in application mode (perhaps executed just a single machine instruction) and then the second signal arrives. Since that second signal is not blocked (that is an assumption being made here) its handler runs immediately. The effect of all of this is that yes, if there are multiple pending unblocked signals, the handlers for all of them will have been run before the pthread_sigmask() function which unblocked them (or some of them) returns. However, I don't think this function needs to require that, and it is possible that there are systems which behave differently. I assume there was some reason that the current text says "at least one of" rather than "all" (at least one doesn't preclude all, so is safe for both variations). To the unimportant parts of the note: I wouldn't expect to find a kill.c file in the kernel sources - the kill sys call is too small to warrant a file of its own - the code for it will be buried elsewhere, though I can't guess where in Illuminos (its name might also be something unexpected - that is, unexpected until you understand why it is called that - that happens sometimes when several semi-related user level functions all channel through one kernel interface - the libc code arranges for the correct thing to happen when a generic routine is called). But having it t_sig_check set by a generic signal delivery function (like that eat_signal() that you found) is how I would do it, though I doubt I would call the function by that name (but who knows). There is however nothing that needs taking care of wrt SIG_BLOCK and t_sig_check - the latter gets set when a pending signal is posted. SIG_BLOCK never causes that to happen, so doesn't need to do anything. And last, just in case it ever seems to be an issue - there is also never a problem (or shouldn't be) if t_sig_check is set, and there is no pending unblocked signal - as its name implies "check" it informs the syscall (and trap, if they're different) exit routine(s) to look for a pending signal. The only effect if it is set, when it "shouldn't be" is for the code to do a little extra work determining that - if nothing is found, it should act just the same, if fractionally slower, than if t_sig_check had not been set. 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 2023-06-07 09:44 geoffclare Note Added: 0006314 2023-06-09 11:24 kre Note Added: 0006316 ======================================================================