Page MenuHomeFreeBSD

pipe: fix POLLHUP handling if no events were specified
ClosedPublic

Authored by mjg on Nov 4 2020, 10:11 PM.
Tags
None
Referenced Files
Unknown Object (File)
Dec 21 2023, 2:41 PM
Unknown Object (File)
Dec 20 2023, 4:14 AM
Unknown Object (File)
Sep 1 2023, 6:57 AM
Unknown Object (File)
Aug 28 2023, 2:28 AM
Unknown Object (File)
Aug 28 2023, 2:26 AM
Unknown Object (File)
Aug 28 2023, 2:26 AM
Unknown Object (File)
Aug 26 2023, 6:57 AM
Unknown Object (File)
Aug 2 2023, 1:00 PM
Subscribers

Details

Summary

Linux allows polling without any events specified and it happens to be the case in FreeBSD as well. POLLHUP has to be delivered regardless of the event mask and this works fine if the condition is already present. However, if it is missing, selrecord is only called if the eventmask has relevant bits set. This in particular leads to a conditon where pipe_poll can return 0 events and neglect to selrecord, while kern_poll takes it as an indication it has to go to sleep, but then there is nobody to wake it up.

The problem is reported here with a reproducer: https://lists.freebsd.org/pipermail/freebsd-hackers/2020-November/056685.html

While the problem seems systemic to *_poll handlers the least we can do is fix it up for pipes.

Test Plan

use the reproducer mentioned above

Diff Detail

Repository
rS FreeBSD src repository - subversion
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

mjg requested review of this revision.Nov 4 2020, 10:11 PM
kib added inline comments.
sys/kern/sys_pipe.c
1465 ↗(On Diff #79188)

Fix style while there, != 0.

1467 ↗(On Diff #79188)

What is the point of rechecking SEL_WAITING after selrecord ?

This revision is now accepted and ready to land.Nov 4 2020, 10:40 PM

src/tools/regression/poll contains some reproducers for corner cases by bde, it is probably worth rechecking with the patch applied.

Fair. I ran it while toggling the patch, got the same outcome in both cases:

1..20
ok 1 Pipe state 4: expected 0; got 0
ok 2 Pipe state 5: expected POLLIN; got POLLIN
ok 3 Pipe state 6: expected POLLIN | POLLHUP; got POLLIN | POLLHUP
not ok 4 Pipe state 6a: expected POLLHUP; got POLLIN | POLLHUP
ok 5 Sock state 4: expected 0; got 0
ok 6 Sock state 5: expected POLLIN; got POLLIN
ok 7 Sock state 6: expected POLLIN | POLLHUP; got POLLIN | POLLHUP
not ok 8 Sock state 6a: expected POLLHUP; got POLLIN | POLLHUP
ok 9 FIFO state 0: expected 0; got 0
ok 10 FIFO state 1: expected 0; got 0
ok 11 FIFO state 2: expected POLLIN; got POLLIN
ok 12 FIFO state 2a: expected 0; got 0
not ok 13 FIFO state 3: expected POLLHUP; got POLLIN | POLLHUP
ok 14 FIFO state 4: expected 0; got 0
ok 15 FIFO state 5: expected POLLIN; got POLLIN
ok 16 FIFO state 6: expected POLLIN | POLLHUP; got POLLIN | POLLHUP
not ok 17 FIFO state 6a: expected POLLHUP; got POLLIN | POLLHUP
not ok 18 FIFO state 6b: poll result 0 expected 1. expected POLLHUP; got 0
not ok 19 FIFO state 6c: expected POLLHUP; got POLLIN | POLLHUP
not ok 20 FIFO state 6d: expected POLLHUP; got POLLIN | POLLHUP

Someone will have to look into expectations here. Given that there is no change with the patch I don't consider this to be a blocker.

sys/kern/sys_pipe.c
1467 ↗(On Diff #79188)

selrecord exits early if SELTD_RESCAN is set

This revision was automatically updated to reflect the committed changes.
In D27094#604770, @mjg wrote:

Someone will have to look into expectations here. Given that there is no change with the patch I don't consider this to be a blocker.

This is fine.