public inbox for cygwin-cvs@sourceware.org
help / color / mirror / Atom feed
* [newlib-cygwin] Cygwin: FIFO: add support for the duplex case
@ 2019-03-27 13:03 Corinna Vinschen
0 siblings, 0 replies; only message in thread
From: Corinna Vinschen @ 2019-03-27 13:03 UTC (permalink / raw)
To: cygwin-cvs
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=a137da74bae803a4770dce9a6f38f1def582fe80
commit a137da74bae803a4770dce9a6f38f1def582fe80
Author: Ken Brown <kbrown@cornell.edu>
Date: Mon Mar 25 23:06:10 2019 +0000
Cygwin: FIFO: add support for the duplex case
If a FIFO is opened with O_RDWR access, create the pipe with
read/write access, and make the first client have the handle of that
pipe as its I/O handle.
Adjust fhandler_fifo::raw_read to account for the result of trying to
read from that client if there's no data.
Diff:
---
winsup/cygwin/fhandler.h | 5 +++
winsup/cygwin/fhandler_fifo.cc | 79 ++++++++++++++++++++++++++++++++++++------
2 files changed, 73 insertions(+), 11 deletions(-)
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index ef34f9c..3398cc6 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -1253,6 +1253,10 @@ struct fifo_client_handler
HANDLE dummy_evt; /* Never signaled. */
fifo_client_handler () : fh (NULL), state (fc_unknown), connect_evt (NULL),
dummy_evt (NULL) {}
+ fifo_client_handler (fhandler_base *_fh, fifo_client_connect_state _state,
+ HANDLE _connect_evt, HANDLE _dummy_evt)
+ : fh (_fh), state (_state), connect_evt (_connect_evt),
+ dummy_evt (_dummy_evt) {}
int connect ();
int close ();
};
@@ -1268,6 +1272,7 @@ class fhandler_fifo: public fhandler_base
fifo_client_handler client[MAX_CLIENTS];
int nclients, nconnected;
af_unix_spinlock_t _fifo_client_lock;
+ bool _duplexer;
bool __reg2 wait (HANDLE);
NTSTATUS npfs_handle (HANDLE &);
HANDLE create_pipe_instance (bool);
diff --git a/winsup/cygwin/fhandler_fifo.cc b/winsup/cygwin/fhandler_fifo.cc
index 2c20444..7847cca 100644
--- a/winsup/cygwin/fhandler_fifo.cc
+++ b/winsup/cygwin/fhandler_fifo.cc
@@ -33,7 +33,7 @@ STATUS_PIPE_EMPTY simply means there's no data to be read. */
fhandler_fifo::fhandler_fifo ():
fhandler_base (), read_ready (NULL), write_ready (NULL),
listen_client_thr (NULL), lct_termination_evt (NULL), nclients (0),
- nconnected (0)
+ nconnected (0), _duplexer (false)
{
pipe_name_buf[0] = L'\0';
need_fork_fixup (true);
@@ -224,6 +224,8 @@ fhandler_fifo::create_pipe_instance (bool first)
}
access = GENERIC_READ | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES
| SYNCHRONIZE;
+ if (first && _duplexer)
+ access |= GENERIC_WRITE;
sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
hattr = OBJ_INHERIT;
if (first)
@@ -437,7 +439,7 @@ fhandler_fifo::open (int flags, mode_t)
case O_RDWR:
reader = true;
writer = false;
- duplexer = true;
+ duplexer = _duplexer = true;
break;
default:
set_errno (EINVAL);
@@ -447,7 +449,7 @@ fhandler_fifo::open (int flags, mode_t)
debug_only_printf ("reader %d, writer %d, duplexer %d", reader, writer, duplexer);
set_flags (flags);
- if (reader)
+ if (reader && !duplexer)
nohandle (true);
/* Create control events for this named pipe */
@@ -472,6 +474,48 @@ fhandler_fifo::open (int flags, mode_t)
goto out;
}
+ /* If we're a duplexer, create the pipe and the first client. */
+ if (duplexer)
+ {
+ HANDLE ph, connect_evt, dummy_evt;
+ fhandler_base *fh;
+
+ ph = create_pipe_instance (true);
+ if (!ph)
+ {
+ res = error_errno_set;
+ goto out;
+ }
+ set_io_handle (ph);
+ set_pipe_non_blocking (ph, true);
+ if (!(fh = build_fh_dev (dev ())))
+ {
+ set_errno (EMFILE);
+ res = error_errno_set;
+ goto out;
+ }
+ fh->set_io_handle (ph);
+ fh->set_flags (flags);
+ if (!(connect_evt = create_event ()))
+ {
+ res = error_errno_set;
+ fh->close ();
+ delete fh;
+ goto out;
+ }
+ if (!(dummy_evt = create_event ()))
+ {
+ res = error_errno_set;
+ delete fh;
+ fh->close ();
+ CloseHandle (connect_evt);
+ goto out;
+ }
+ client[0] = fifo_client_handler (fh, fc_connected, connect_evt,
+ dummy_evt);
+ nconnected = nclients = 1;
+ }
+
/* If we're reading, start the listen_client thread (which should
signal read_ready), and wait for a writer. */
if (reader)
@@ -482,8 +526,8 @@ fhandler_fifo::open (int flags, mode_t)
res = error_errno_set;
goto out;
}
- /* Wait for the listen_client thread to create the pipe and
- signal read_ready. This should be quick. */
+ /* Wait for the listen_client thread to signal read_ready. This
+ should be quick. */
HANDLE w[2] = { listen_client_thr, read_ready };
switch (WaitForMultipleObjects (2, w, FALSE, INFINITE))
{
@@ -703,12 +747,25 @@ fhandler_fifo::raw_read (void *in_ptr, size_t& len)
fifo_client_unlock ();
return;
}
- else if (nread < 0 && GetLastError () != ERROR_NO_DATA)
- {
- fifo_client_unlock ();
- goto errout;
- }
- else if (nread == 0) /* Client has disconnected. */
+ /* In the duplex case with no data, we seem to get nread
+ == -1 with ERROR_PIPE_LISTENING on the first attempt to
+ read from the duplex pipe (client[0]), and nread == 0
+ on subsequent attempts. */
+ else if (nread < 0)
+ switch (GetLastError ())
+ {
+ case ERROR_NO_DATA:
+ break;
+ case ERROR_PIPE_LISTENING:
+ if (_duplexer && i == 0)
+ break;
+ /* Fall through. */
+ default:
+ fifo_client_unlock ();
+ goto errout;
+ }
+ else if (nread == 0 && (!_duplexer || i > 0))
+ /* Client has disconnected. */
{
client[i].state = fc_invalid;
nconnected--;
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2019-03-27 13:03 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-03-27 13:03 [newlib-cygwin] Cygwin: FIFO: add support for the duplex case Corinna Vinschen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).