The following issue has been SUBMITTED. ====================================================================== http://austingroupbugs.net/view.php?id=1186 ====================================================================== Reported By: davmac Assigned To: ====================================================================== Project: 1003.1(2016)/Issue7+TC2 Issue ID: 1186 Category: System Interfaces Type: Clarification Requested Severity: Editorial Priority: normal Status: New Name: Davin McCall Organization: User Reference: Section: pselect Page Number: 1554-1555 Line Number: 50880 Interp Status: --- Final Accepted Text: ====================================================================== Date Submitted: 2018-02-02 18:47 UTC Last Modified: 2018-02-02 18:47 UTC ====================================================================== Summary: pselect specification allows for race condition that pselect was created to avoid Description: As I understand it the pselect() function was created to avoid a race condition when watching for file descriptor readiness and simultaneously waiting on a signal. Typically the signal handler merely sets a flag and an application using select() can check the flag if select is interrupted and returns EINTR; The problem is that the signal can occur just before entry to select() and therefore not be noticed by the application until after select() returns. The pselect() function was supposed to solve this problem by allowing the signal(s) be "atomically" unmasked before starting to wait for file descriptor readiness (and masked again afterwards).
The current wording says only: "If sigmask is not a null pointer, then the pselect( ) function shall replace the signal mask of the caller by the set of signals pointed to by sigmask before examining the descriptors, and shall restore the signal mask of the calling thread before returning." This by itself would allow pselect to be implemented in terms of sigprocmask (or pthread_sigmask) and the original select function; however, such an implemented would be prone to the original race condition that pselect is supposed to avoid. The following text also appears in the description: 50863 "If none of the selected descriptors are ready for the requested operation, the pselect( ) or select( ) function shall block until at least one of the requested operations becomes ready, until the timeout occurs, or until interrupted by a signal" (...) However "block until ... interrupted" does not imply that a signal arriving before blocking starts should not cause the function to return without blocking. Nowhere in the text is it stated that there is not a window between the unmasking of signals as per the provided signal mask and the examination of the file descriptors in which an unmasked signal can be delivered, as needs to be the case if pselect() is usable to avoid the race condition that is its raison d'être. Furthermore the function can return EINTR only in the following conditions: 50963 "[EINTR] The function was interrupted while blocked waiting for any of the selected descriptors to become ready and before the timeout interval expired." This requires that the function is already blocked and waiting when the signal arrives if EINTR is to be returned, leaving open the possibility that the signal is received after it is unmasked but before the blocking/waiting occurs. There is an additional, less drastic, issue: as well as the signal arriving between the unmasking and blocking, one might arrive between blocking (after a file descriptor has become ready) and the re-masking of signals. This is less drastic because an application that is ready for this can inspect the flag variable that the signal handler should set whenever pselect() returns. However, it seems likely that many applications will run under the assumption that if pselect() does not return with EINTR, then none of the temporarily-masked signals were handled during its execution, which seems like it should be true according to the reasoning for the creation of the interface (but again, which is not implied by the text describing the interface). A final concern is what happens when pselect() is called when both file descriptors in the specified sets are ready and signals are pending. The text regarding EINTR implies that the function will not return EINTR in this case, since the functional cannot be interrupted while blocking if it does not in fact block. While there is no fundamental problem with this requirement, it is adds at least with the Linux implementation of pselect, and probably with others. Desired Action: Change the paragraph at 50880, appending: "If a signal is unmasked as a result of the signal mask being altered by pselect(), and that signal is delivered during the execution of the pselect() function, and the signal action does not restart interruptible functions, then pselect shall immediately fail with the EINTR error after delivery of the signal." Change the paragraph at 50963 to: "[EINTR] The function was interrupted by a signal." ====================================================================== Issue History Date Modified Username Field Change ====================================================================== 2018-02-02 18:47 davmac New Issue 2018-02-02 18:47 davmac Name => Davin McCall 2018-02-02 18:47 davmac Section => pselect 2018-02-02 18:47 davmac Page Number => 1554-1555 2018-02-02 18:47 davmac Line Number => 50880 ======================================================================