poll, pselect: handle POLLPRI / errorfds gracefully#754
poll, pselect: handle POLLPRI / errorfds gracefully#754paralin wants to merge 1 commit intoWebAssembly:mainfrom
Conversation
|
vim and other programs hit this ENOSYS and break/exit; so returning all-zero is correct. in practice there are only two cases I found where these "exceptional cases" would ever occur:
exceptfds doesn't report general errors like broken pipe or connection reset, these would show up as errors via getsockopt(SO_ERROR). |
|
Reading over the Personally it feels incorrect to me to ignore parameters and proceed since if those were the only fds set, for example, then there's no way for the function to wake up. Overall I feel that returning an error for "you requested to do something that isn't implementable" is the right behavior here as it's an accurate reflection of the state of the world. Would it be possible to patch the application you're working with to avoid using |
|
It's obviously possible to patch the programs, but I have a feeling it would end up becoming a nightmare patching every single program that calls this API. Fwiw, I tested it and it works correctly with the PR as is. If there's a more correct way to do it, I can look into it. Emulating the condition never happening seems to make sense to me, for compatibility, as opposed to ENOSYS, particularly with it being such a rare condition anyway. But I understand if you want to reject. I guess I could send a PR to vim to handle ENOSYS for this call properly. |
|
How about a variation of this:
That should get If so would you be up for including a test here as well to exercise this new behavior? |
|
I'll work on it! Thanks! |
|
@alexcrichton POLLPRI - usually
I defined it in my PR as 0x0200 since that was unused. It's only used internally and never passed to the WASI API, so I think this is ok. This still makes me a bit nervous as I worry that some programs will only sometimes call this with exclusively POLLPRI fds, get an unexpected ENOSYS, and crash, and now it'll be a bit harder to predict if this will happen as it's only sometimes that it will return ENOSYS. I added the test as requested - ready for your review. |
WASI has no out-of-band data, so POLLPRI can never fire. Rather than rejecting any use of POLLPRI outright, adopt a lenient policy: - Define POLLPRI in __header_poll.h for source compatibility. - In poll(): if any fd requests non-POLLPRI events, strip POLLPRI and proceed (it simply never fires). Only return ENOSYS when every fd exclusively requests POLLPRI, since there is nothing useful to poll. - In pselect(): thread errorfds through poll() as POLLPRI entries so the call succeeds when readfds or writefds are also provided. This fixes programs (e.g. vim) that pass errorfds to select/pselect alongside other fd sets. Includes a test exercising pselect with errorfds and poll with POLLPRI. See: WebAssembly#754 (comment) Signed-off-by: Christian Stewart <christian@aperture.us>
c0d23c8 to
cdf682d
Compare
WASI has no out-of-band data, so POLLPRI can never fire. Rather than rejecting any use of POLLPRI outright, adopt a lenient policy: - Define POLLPRI in __header_poll.h for source compatibility. - In poll(): if any fd requests non-POLLPRI events, strip POLLPRI and proceed (it simply never fires). Only return ENOSYS when every fd exclusively requests POLLPRI, since there is nothing useful to poll. - In pselect(): thread errorfds through poll() as POLLPRI entries so the call succeeds when readfds or writefds are also provided. This fixes programs (e.g. vim) that pass errorfds to select/pselect alongside other fd sets. Includes a test exercising pselect with errorfds and poll with POLLPRI. See: WebAssembly#754 (comment) Signed-off-by: Christian Stewart <christian@aperture.us>
cdf682d to
8260d16
Compare
WASI has no out-of-band data, so POLLPRI can never fire. Rather than rejecting any use of POLLPRI outright, adopt a lenient policy: - Define POLLPRI in __header_poll.h for source compatibility. - In poll(): if any fd requests non-POLLPRI events, strip POLLPRI and proceed (it simply never fires). Only return ENOSYS when every fd exclusively requests POLLPRI, since there is nothing useful to poll. - In pselect(): thread errorfds through poll() as POLLPRI entries so the call succeeds when readfds or writefds are also provided. This fixes programs (e.g. vim) that pass errorfds to select/pselect alongside other fd sets. Includes a test exercising pselect with errorfds and poll with POLLPRI. See: WebAssembly#754 (comment) Signed-off-by: Christian Stewart <christian@aperture.us>
8260d16 to
c68ff2c
Compare
WASI has no out-of-band data, so POLLPRI can never fire. Rather than rejecting any use of POLLPRI outright, adopt a lenient policy: - Define POLLPRI in __header_poll.h for source compatibility. - In poll(): if any fd requests non-POLLPRI events, strip POLLPRI and proceed (it simply never fires). Only return ENOSYS when every fd exclusively requests POLLPRI, since there is nothing useful to poll. - In pselect(): thread errorfds through poll() as POLLPRI entries so the call succeeds when readfds or writefds are also provided. This fixes programs (e.g. vim) that pass errorfds to select/pselect alongside other fd sets. Includes a test exercising pselect with errorfds and poll with POLLPRI. See: WebAssembly#754 (comment) Signed-off-by: Christian Stewart <christian@aperture.us>
c68ff2c to
19c51b1
Compare
|
CI green 👍🏽 |
|
Reading over this it all looks pretty good, thanks! W.r.t You have a good point though, and it also raises another question for me. You say that vim and other programs were the impetus here, but do know of more details about the use case here? For example do you know if these applications just blanket insert |
pselect() returned ENOSYS when errorfds had any bits set. This breaks programs that use the standard POSIX pattern of passing exceptfds to select() for EOF/error monitoring (e.g., vim, ncurses applications).
Since WASI has no out-of-band data mechanism, errorfds can never have any exceptional conditions to report. Clear it instead of rejecting the call, matching the behavior callers expect from a POSIX-compatible select().