The following issue has been SUBMITTED. 
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 
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
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

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

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           

Reply via email to