Page MenuHomeFreeBSD

Fix pipe_poll() after r349546.
ClosedPublic

Authored by markj on Aug 20 2019, 1:24 AM.

Details

Summary

Recall from r349546 that PIPE_DIRECTW is a semaphore used to provide
mutual exclusion for the pipe_map fields (note that it is unrelated to
the global pipe_map). These fields hold an array of pages mapped in to
the writer until the reader drains them. PIPE_DIRECTW provides mutual
exclusion among multiple writers; prior to r349546, a reader would clear
PIPE_DIRECTW after draining the data, but this was incorrect because the
writer is responsible for doing run-down of the pipe_map fields.

r349546 changes things so that the writer clears PIPE_DIRECTW after the
reader drains data and wakes the writer up. However, this broke
pipe_poll() since it returned POLLIN if PIPE_DIRECTW is set. If
pipe_poll() executes after a reader has drained all data and before the
writer clears PIPE_DIRECTW, it would return POLLIN even though no data
is present.

Fix this by replacing most checks for PIPE_DIRECTW with tests for
pipe_map.cnt != 0. We still test PIPE_DIRECTW in filt_pipewrite() and
pipe_poll(POLLOUT) since a writer may block whenever PIPE_DIRECTW is
set.

Test Plan

I tested using a python script from mav that exposes the race. I will ask
Peter to test.

Diff Detail

Repository
rS FreeBSD src repository
Lint
Automatic diff as part of commit; lint not applicable.
Unit
Automatic diff as part of commit; unit tests not applicable.

Event Timeline

markj created this revision.Aug 20 2019, 1:24 AM
markj edited the summary of this revision. (Show Details)Aug 20 2019, 1:27 AM
markj edited the test plan for this revision. (Show Details)
markj added reviewers: kib, mjg.
markj added a subscriber: mav.
kib accepted this revision.Aug 20 2019, 9:01 AM
This revision is now accepted and ready to land.Aug 20 2019, 9:01 AM
This revision was automatically updated to reflect the committed changes.