summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/fhandler.h8
-rw-r--r--winsup/cygwin/fhandler_fifo.cc22
2 files changed, 22 insertions, 8 deletions
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 8d6b94021..b2ee7e6b6 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -1303,6 +1303,11 @@ struct fifo_client_handler
/* Info needed by all readers of a FIFO, stored in named shared memory. */
class fifo_shmem_t
{
+ LONG _nreaders;
+
+public:
+ int inc_nreaders () { return (int) InterlockedIncrement (&_nreaders); }
+ int dec_nreaders () { return (int) InterlockedDecrement (&_nreaders); }
};
class fhandler_fifo: public fhandler_base
@@ -1342,6 +1347,9 @@ class fhandler_fifo: public fhandler_base
int create_shmem ();
int reopen_shmem ();
+ int inc_nreaders () { return shmem->inc_nreaders (); }
+ int dec_nreaders () { return shmem->dec_nreaders (); }
+
public:
fhandler_fifo ();
bool hit_eof ();
diff --git a/winsup/cygwin/fhandler_fifo.cc b/winsup/cygwin/fhandler_fifo.cc
index 9a0db3f33..d87070ac7 100644
--- a/winsup/cygwin/fhandler_fifo.cc
+++ b/winsup/cygwin/fhandler_fifo.cc
@@ -570,8 +570,9 @@ fhandler_fifo::open (int flags, mode_t)
SetEvent (read_ready);
if (create_shmem () < 0)
goto err_close_writer_opening;
+ inc_nreaders ();
if (!(cancel_evt = create_event ()))
- goto err_close_shmem;
+ goto err_dec_nreaders;
if (!(thr_sync_evt = create_event ()))
goto err_close_cancel_evt;
new cygthread (fifo_reader_thread, this, "fifo_reader", thr_sync_evt);
@@ -680,7 +681,10 @@ err_close_reader:
return 0;
err_close_cancel_evt:
NtClose (cancel_evt);
-err_close_shmem:
+err_dec_nreaders:
+ if (dec_nreaders () == 0)
+ ResetEvent (read_ready);
+/* err_close_shmem: */
NtUnmapViewOfSection (NtCurrentProcess (), shmem);
NtClose (shmem_handle);
err_close_writer_opening:
@@ -1003,15 +1007,13 @@ fhandler_fifo::close ()
{
if (reader)
{
+ if (dec_nreaders () == 0)
+ ResetEvent (read_ready);
cancel_reader_thread ();
if (cancel_evt)
NtClose (cancel_evt);
if (thr_sync_evt)
NtClose (thr_sync_evt);
- /* FIXME: There could be several readers open because of
- dup/fork/exec; we should only reset read_ready when the last
- one closes. */
- ResetEvent (read_ready);
if (shmem)
NtUnmapViewOfSection (NtCurrentProcess (), shmem);
if (shmem_handle)
@@ -1116,8 +1118,8 @@ fhandler_fifo::dup (fhandler_base *child, int flags)
goto err_close_handlers;
if (!(fhf->thr_sync_evt = create_event ()))
goto err_close_cancel_evt;
- new cygthread (fifo_reader_thread, fhf, "fifo_reader",
- fhf->thr_sync_evt);
+ inc_nreaders ();
+ new cygthread (fifo_reader_thread, fhf, "fifo_reader", fhf->thr_sync_evt);
}
return 0;
err_close_cancel_evt:
@@ -1161,6 +1163,7 @@ fhandler_fifo::fixup_after_fork (HANDLE parent)
api_fatal ("Can't create reader thread cancel event during fork, %E");
if (!(thr_sync_evt = create_event ()))
api_fatal ("Can't create reader thread sync event during fork, %E");
+ inc_nreaders ();
new cygthread (fifo_reader_thread, this, "fifo_reader", thr_sync_evt);
}
}
@@ -1180,6 +1183,9 @@ fhandler_fifo::fixup_after_exec ()
api_fatal ("Can't create reader thread cancel event during exec, %E");
if (!(thr_sync_evt = create_event ()))
api_fatal ("Can't create reader thread sync event during exec, %E");
+ /* At this moment we're a new reader. The count will be
+ decremented when the parent closes. */
+ inc_nreaders ();
new cygthread (fifo_reader_thread, this, "fifo_reader", thr_sync_evt);
}
}