* fhandler.h (fhandler_fifo::arm): Declare new function.

* fhandler_fifo.cc (fhandler_fifo::arm): Define new function.
(fhandler_fifo::open): Fix handling of RDWR pipes to avoid opening a second
handle.  Use arm() function to set events.
(fhandler_fifo::raw_read): Correctly go into "connect again logic" when we
detect another writer is available.  Use arm() function to set event.
* pipe.cc (fhandler_pipe::create): Add more detail to debugging output.
This commit is contained in:
Christopher Faylor 2012-01-22 21:43:25 +00:00
parent 5b09af7a51
commit 1ad58ee709
4 changed files with 49 additions and 20 deletions

View File

@ -1,3 +1,13 @@
2012-01-22 Christopher Faylor <me.cygwin2012@cgf.cx>
* fhandler.h (fhandler_fifo::arm): Declare new function.
* fhandler_fifo.cc (fhandler_fifo::arm): Define new function.
(fhandler_fifo::open): Fix handling of RDWR pipes to avoid opening a
second handle. Use arm() function to set events.
(fhandler_fifo::raw_read): Correctly go into "connect again logic" when
we detect another writer is available. Use arm() function to set event.
* pipe.cc (fhandler_pipe::create): Add more detail to debugging output.
2012-01-22 Christopher Faylor <me.cygwin2012@cgf.cx>
* cygheap.h (cygheap_fdmanip::release): Simplify.

View File

@ -738,6 +738,7 @@ public:
bool isfifo () const { return true; }
void set_close_on_exec (bool val);
void __stdcall raw_read (void *ptr, size_t& ulen) __attribute__ ((regparm (3)));
bool arm (HANDLE h);
void fixup_after_fork (HANDLE);
int __stdcall fstatvfs (struct statvfs *buf) __attribute__ ((regparm (2)));
select_record *select_read (select_stuff *);

View File

@ -1,6 +1,6 @@
/* fhandler_fifo.cc - See fhandler.h for a description of the fhandler classes.
Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
Red Hat, Inc.
This file is part of Cygwin.
@ -51,6 +51,26 @@ sec_user_cloexec (bool cloexec, PSECURITY_ATTRIBUTES sa, PSID sid)
return cloexec ? sec_user_nih (sa, sid) : sec_user (sa, sid);
}
bool inline
fhandler_fifo::arm (HANDLE h)
{
#ifdef DEBUGGING
const char *what;
if (h == read_ready)
what = "reader";
else if (h == write_ready)
what = "writer";
else
what = "overlapped event";
debug_only_printf ("arming %s", what);
#endif
bool res = SetEvent (h);
if (!res)
debug_printf ("SetEvent for %s failed, %E", res);
return res;
}
int
fhandler_fifo::open (int flags, mode_t)
{
@ -60,7 +80,7 @@ fhandler_fifo::open (int flags, mode_t)
error_errno_set,
error_set_errno
} res;
bool reader, writer;
bool reader, writer, duplexer;
DWORD open_mode = FILE_FLAG_OVERLAPPED;
/* Determine what we're doing with this fhandler: reading, writing, both */
@ -69,15 +89,18 @@ fhandler_fifo::open (int flags, mode_t)
case O_RDONLY:
reader = true;
writer = false;
duplexer = false;
break;
case O_WRONLY:
writer = true;
reader = false;
duplexer = false;
break;
case O_RDWR:
reader = true;
writer = true;
open_mode |= PIPE_ACCESS_DUPLEX;
reader = true;
writer = false;
duplexer = true;
break;
default:
set_errno (EINVAL);
@ -85,6 +108,7 @@ fhandler_fifo::open (int flags, mode_t)
goto out;
}
debug_only_printf ("reader %d, writer %d, duplexer %d", reader, writer, duplexer);
set_flags (flags);
char char_sa_buf[1024];
LPSECURITY_ATTRIBUTES sa_buf;
@ -93,13 +117,13 @@ fhandler_fifo::open (int flags, mode_t)
char npbuf[MAX_PATH];
/* Create control events for this named pipe */
if (!(read_ready = CreateEvent (sa_buf, true, false, fnevent ("r"))))
if (!(read_ready = CreateEvent (sa_buf, duplexer, false, fnevent ("r"))))
{
debug_printf ("CreatEvent for %s failed, %E", npbuf);
res = error_set_errno;
goto out;
}
if (!(write_ready = CreateEvent (sa_buf, true, false, fnevent ("w"))))
if (!(write_ready = CreateEvent (sa_buf, false, false, fnevent ("w"))))
{
debug_printf ("CreatEvent for %s failed, %E", npbuf);
res = error_set_errno;
@ -117,15 +141,13 @@ fhandler_fifo::open (int flags, mode_t)
res = error_set_errno;
goto out;
}
else if (!SetEvent (read_ready))
else if (!arm (read_ready))
{
debug_printf ("SetEvent for read_ready failed, %E");
res = error_set_errno;
goto out;
}
else if (!writer && !wait (write_ready))
else if (!duplexer && !wait (write_ready))
{
debug_printf ("wait for write_ready failed, %E");
res = error_errno_set;
goto out;
}
@ -159,9 +181,8 @@ fhandler_fifo::open (int flags, mode_t)
res = error_set_errno;
goto out;
}
if (!SetEvent (write_ready))
if (!arm (write_ready))
{
debug_printf ("SetEvent for write_ready failed, %E");
res = error_set_errno;
goto out;
}
@ -255,7 +276,7 @@ fhandler_fifo::raw_read (void *in_ptr, size_t& len)
for (int i = 0; i < 2; i++)
{
fhandler_base_overlapped::raw_read (in_ptr, len);
if (len || i || WaitForSingleObject (read_ready, 0) == WAIT_OBJECT_0)
if (len || i || WaitForSingleObject (read_ready, 0) != WAIT_OBJECT_0)
break;
/* If we got here, then fhandler_base_overlapped::raw_read returned 0,
indicating "EOF" and something has set read_ready to zero. That means
@ -273,11 +294,8 @@ fhandler_fifo::raw_read (void *in_ptr, size_t& len)
debug_printf ("ConnectNamedPipe failed, %E");
goto errno_out;
}
else if (!SetEvent (read_ready))
{
debug_printf ("SetEvent (read_ready) failed, %E");
goto errno_out;
}
else if (!arm (read_ready))
goto errno_out;
else if (!wait (get_overlapped_buffer ()->hEvent))
goto errout; /* If wait() fails, errno is set so no need to set it */
len = orig_len; /* Reset since raw_read above set it to zero. */

View File

@ -1,7 +1,7 @@
/* pipe.cc: pipe for Cygwin.
Copyright 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
2008, 2009, 2010, 2011 Hat, Inc.
2008, 2009, 2010, 2011, 2011 Hat, Inc.
This file is part of Cygwin.
@ -306,7 +306,7 @@ fhandler_pipe::create (LPSECURITY_ATTRIBUTES sa_ptr, PHANDLE r, PHANDLE w,
{
/* Failure. */
DWORD err = GetLastError ();
debug_printf ("CreateFile failed, %E");
debug_printf ("CreateFile failed, r %p, %E", r);
if (r)
CloseHandle (*r);
*w = NULL;