Cygwin: FIFO: designate one reader as owner

Among all the open readers of a FIFO, one is declared to be the owner.
This is the only reader that listens for client connections, and it is
the only one that has an accurate fc_handler list.

Add shared data and methods for getting and setting the owner, as well
as a lock to prevent more than one reader from accessing these data
simultaneously.

Modify the fifo_reader_thread so that it checks the owner at the
beginning of its loop.  If there is no owner, it takes ownership.  If
there is an owner but it is a different reader, the thread just waits
to be canceled.  Otherwise, it listens for client connections as
before.

Remove the 'first' argument from create_pipe_instance.  It is not
needed, and it may be confusing in the future since only the owner
knows whether a pipe instance is the first.

When opening a reader, don't return until the fifo_reader_thread has
time to set an owner.

If the owner closes, indicate that there is no longer an owner.

Clear the child's fc_handler list in dup, and don't bother duplicating
the handles.  The child never starts out as owner, so it can't use
those handles.

Do the same thing in fixup_after_fork in the close-on-exec case.  In
the non-close-on-exec case, the child inherits an fc_handler list that
it can't use, but we can just leave it alone; the handles will be
closed when the child is closed.
This commit is contained in:
Ken Brown
2020-03-26 14:32:10 -04:00
parent 16e7c10578
commit 606baf5566
2 changed files with 143 additions and 111 deletions

View File

@ -1324,10 +1324,17 @@ struct fifo_reader_id_t
class fifo_shmem_t
{
LONG _nreaders;
fifo_reader_id_t _owner;
af_unix_spinlock_t _owner_lock;
public:
int inc_nreaders () { return (int) InterlockedIncrement (&_nreaders); }
int dec_nreaders () { return (int) InterlockedDecrement (&_nreaders); }
fifo_reader_id_t get_owner () const { return _owner; }
void set_owner (fifo_reader_id_t fr_id) { _owner = fr_id; }
void owner_lock () { _owner_lock.lock (); }
void owner_unlock () { _owner_lock.unlock (); }
};
class fhandler_fifo: public fhandler_base
@ -1356,7 +1363,7 @@ class fhandler_fifo: public fhandler_base
bool __reg2 wait (HANDLE);
static NTSTATUS npfs_handle (HANDLE &);
HANDLE create_pipe_instance (bool);
HANDLE create_pipe_instance ();
NTSTATUS open_pipe (HANDLE&);
NTSTATUS wait_open_pipe (HANDLE&);
int add_client_handler ();
@ -1384,6 +1391,10 @@ public:
void fifo_client_unlock () { _fifo_client_lock.unlock (); }
fifo_reader_id_t get_me () const { return me; }
fifo_reader_id_t get_owner () const { return shmem->get_owner (); }
void set_owner (fifo_reader_id_t fr_id) { shmem->set_owner (fr_id); }
void owner_lock () { shmem->owner_lock (); }
void owner_unlock () { shmem->owner_unlock (); }
int open (int, mode_t);
off_t lseek (off_t offset, int whence);