* 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> 2012-01-22 Christopher Faylor <me.cygwin2012@cgf.cx>
* cygheap.h (cygheap_fdmanip::release): Simplify. * cygheap.h (cygheap_fdmanip::release): Simplify.

View File

@ -738,6 +738,7 @@ public:
bool isfifo () const { return true; } bool isfifo () const { return true; }
void set_close_on_exec (bool val); void set_close_on_exec (bool val);
void __stdcall raw_read (void *ptr, size_t& ulen) __attribute__ ((regparm (3))); void __stdcall raw_read (void *ptr, size_t& ulen) __attribute__ ((regparm (3)));
bool arm (HANDLE h);
void fixup_after_fork (HANDLE); void fixup_after_fork (HANDLE);
int __stdcall fstatvfs (struct statvfs *buf) __attribute__ ((regparm (2))); int __stdcall fstatvfs (struct statvfs *buf) __attribute__ ((regparm (2)));
select_record *select_read (select_stuff *); 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. /* 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. Red Hat, Inc.
This file is part of Cygwin. 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); 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 int
fhandler_fifo::open (int flags, mode_t) fhandler_fifo::open (int flags, mode_t)
{ {
@ -60,7 +80,7 @@ fhandler_fifo::open (int flags, mode_t)
error_errno_set, error_errno_set,
error_set_errno error_set_errno
} res; } res;
bool reader, writer; bool reader, writer, duplexer;
DWORD open_mode = FILE_FLAG_OVERLAPPED; DWORD open_mode = FILE_FLAG_OVERLAPPED;
/* Determine what we're doing with this fhandler: reading, writing, both */ /* 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: case O_RDONLY:
reader = true; reader = true;
writer = false; writer = false;
duplexer = false;
break; break;
case O_WRONLY: case O_WRONLY:
writer = true; writer = true;
reader = false; reader = false;
duplexer = false;
break; break;
case O_RDWR: case O_RDWR:
reader = true;
writer = true;
open_mode |= PIPE_ACCESS_DUPLEX; open_mode |= PIPE_ACCESS_DUPLEX;
reader = true;
writer = false;
duplexer = true;
break; break;
default: default:
set_errno (EINVAL); set_errno (EINVAL);
@ -85,6 +108,7 @@ fhandler_fifo::open (int flags, mode_t)
goto out; goto out;
} }
debug_only_printf ("reader %d, writer %d, duplexer %d", reader, writer, duplexer);
set_flags (flags); set_flags (flags);
char char_sa_buf[1024]; char char_sa_buf[1024];
LPSECURITY_ATTRIBUTES sa_buf; LPSECURITY_ATTRIBUTES sa_buf;
@ -93,13 +117,13 @@ fhandler_fifo::open (int flags, mode_t)
char npbuf[MAX_PATH]; char npbuf[MAX_PATH];
/* Create control events for this named pipe */ /* 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); debug_printf ("CreatEvent for %s failed, %E", npbuf);
res = error_set_errno; res = error_set_errno;
goto out; 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); debug_printf ("CreatEvent for %s failed, %E", npbuf);
res = error_set_errno; res = error_set_errno;
@ -117,15 +141,13 @@ fhandler_fifo::open (int flags, mode_t)
res = error_set_errno; res = error_set_errno;
goto out; goto out;
} }
else if (!SetEvent (read_ready)) else if (!arm (read_ready))
{ {
debug_printf ("SetEvent for read_ready failed, %E");
res = error_set_errno; res = error_set_errno;
goto out; 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; res = error_errno_set;
goto out; goto out;
} }
@ -159,9 +181,8 @@ fhandler_fifo::open (int flags, mode_t)
res = error_set_errno; res = error_set_errno;
goto out; goto out;
} }
if (!SetEvent (write_ready)) if (!arm (write_ready))
{ {
debug_printf ("SetEvent for write_ready failed, %E");
res = error_set_errno; res = error_set_errno;
goto out; goto out;
} }
@ -255,7 +276,7 @@ fhandler_fifo::raw_read (void *in_ptr, size_t& len)
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
fhandler_base_overlapped::raw_read (in_ptr, len); 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; break;
/* If we got here, then fhandler_base_overlapped::raw_read returned 0, /* If we got here, then fhandler_base_overlapped::raw_read returned 0,
indicating "EOF" and something has set read_ready to zero. That means 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"); debug_printf ("ConnectNamedPipe failed, %E");
goto errno_out; goto errno_out;
} }
else if (!SetEvent (read_ready)) else if (!arm (read_ready))
{ goto errno_out;
debug_printf ("SetEvent (read_ready) failed, %E");
goto errno_out;
}
else if (!wait (get_overlapped_buffer ()->hEvent)) else if (!wait (get_overlapped_buffer ()->hEvent))
goto errout; /* If wait() fails, errno is set so no need to set it */ 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. */ len = orig_len; /* Reset since raw_read above set it to zero. */

View File

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