summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/ChangeLog29
-rw-r--r--winsup/cygwin/fhandler.cc75
-rw-r--r--winsup/cygwin/fhandler.h39
-rw-r--r--winsup/cygwin/pipe.cc7
4 files changed, 103 insertions, 47 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 3224cf62e..8e85d5906 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,32 @@
+2010-03-31 Christopher Faylor <me+cygwin@cgf.cx>
+
+ * fhandler.cc (fhandler_base::dup): Call setup_overlapped
+ unconditionally.
+ (fhandler_base::fork_fixup): Ditto.
+ (fhandler_base::fixup_after_fork): Ditto.
+ (fhandler_base::fixup_after_exec): Ditto.
+ (fhandler_base_overlapped::setup_overlapped): Move to this class from
+ fhandler_base.
+ (handler_base_overlapped::destroy_overlapped): Ditto.
+ (fhandler_base_overlapped::wait_overlapped): Ditto. Track when we
+ expect pending I/O.
+ (fhandler_base_overlapped::read_overlapped): Move to this class from
+ fhandler_base. Return error if ongoing I/O.
+ (fhandler_base_overlapped::write_overlapped): Ditto.
+ (fhandler_base_overlapped::has_ongoing_io): Semi-reinstate previous
+ function.
+ * fhandler.h (fhandler_base::wait_overlapped): Move to
+ fhandler_base_overlapped class.
+ (fhandler_base::write_overlapped): Ditto.
+ (fhandler_base::get_overlapped): Ditto.
+ (fhandler_base::get_overlapped_buffer): Ditto.
+ (fhandler_base_overlapped): New class.
+ (fhandler_pipe): Inherit from fhandler_base_overlapped. Remove
+ overlapped stuff as a result.
+ (fhandler_fifo): Ditto.
+ * pipe.cc (fhandler_pipe::fhandler_pipe): Initialize fhandler_base_overlapped.
+ (pipe): Put a descriptive name in the fhandler.
+
2010-03-30 Corinna Vinschen <corinna@vinschen.de>
* fhandler_socket.cc (fhandler_socket::wait_for_events): Remove call to
diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc
index 0e0981fdc..704d7a210 100644
--- a/winsup/cygwin/fhandler.cc
+++ b/winsup/cygwin/fhandler.cc
@@ -1162,8 +1162,7 @@ fhandler_base::dup (fhandler_base *child)
VerifyHandle (nh);
child->set_io_handle (nh);
}
- if (get_overlapped ())
- child->setup_overlapped ();
+ child->setup_overlapped ();
return 0;
}
@@ -1335,8 +1334,7 @@ fhandler_base::fork_fixup (HANDLE parent, HANDLE &h, const char *name)
VerifyHandle (h);
res = true;
}
- if (get_overlapped ())
- setup_overlapped ();
+ setup_overlapped ();
return res;
}
@@ -1355,8 +1353,7 @@ fhandler_base::fixup_after_fork (HANDLE parent)
debug_printf ("inheriting '%s' from parent", get_name ());
if (!nohandle ())
fork_fixup (parent, io_handle, "io_handle");
- if (get_overlapped ())
- setup_overlapped ();
+ setup_overlapped ();
/* POSIX locks are not inherited across fork. */
if (unique_id)
del_my_locks (after_fork);
@@ -1366,8 +1363,7 @@ void
fhandler_base::fixup_after_exec ()
{
debug_printf ("here for '%s'", get_name ());
- if (get_overlapped ())
- setup_overlapped ();
+ setup_overlapped ();
if (unique_id && close_on_exec ())
del_my_locks (after_exec);
}
@@ -1645,7 +1641,7 @@ fhandler_base::fpathconf (int v)
/* Overlapped I/O */
bool
-fhandler_base::setup_overlapped (bool doit)
+fhandler_base_overlapped::setup_overlapped (bool doit)
{
OVERLAPPED *ov = get_overlapped_buffer ();
memset (ov, 0, sizeof (*ov));
@@ -1664,7 +1660,7 @@ fhandler_base::setup_overlapped (bool doit)
}
void
-fhandler_base::destroy_overlapped ()
+fhandler_base_overlapped::destroy_overlapped ()
{
OVERLAPPED *ov = get_overlapped ();
if (ov && ov->hEvent)
@@ -1674,8 +1670,22 @@ fhandler_base::destroy_overlapped ()
}
}
+bool
+fhandler_base_overlapped::has_ongoing_io ()
+{
+ if (!io_pending)
+ return false;
+ if (WaitForSingleObject (get_overlapped ()->hEvent, 0) != WAIT_OBJECT_0)
+ {
+ set_errno (EAGAIN);
+ return true;
+ }
+ io_pending = false;
+ return false;
+}
+
int
-fhandler_base::wait_overlapped (bool inres, bool writing, DWORD *bytes, DWORD len)
+fhandler_base_overlapped::wait_overlapped (bool inres, bool writing, DWORD *bytes, DWORD len)
{
if (!get_overlapped ())
return inres;
@@ -1687,6 +1697,7 @@ fhandler_base::wait_overlapped (bool inres, bool writing, DWORD *bytes, DWORD le
{
if (inres || err == ERROR_IO_PENDING)
{
+ io_pending = err == ERROR_IO_PENDING;
if (writing && !inres)
*bytes = len; /* This really isn't true but it seems like
this is a corner-case for linux's
@@ -1758,32 +1769,38 @@ fhandler_base::wait_overlapped (bool inres, bool writing, DWORD *bytes, DWORD le
}
void __stdcall
-fhandler_base::read_overlapped (void *ptr, size_t& len)
+fhandler_base_overlapped::read_overlapped (void *ptr, size_t& len)
{
DWORD nbytes;
- while (1)
- {
- bool res = ReadFile (get_handle (), ptr, len, &nbytes,
- get_overlapped ());
- int wres = wait_overlapped (res, false, &nbytes);
- if (wres || !_my_tls.call_signal_handler ())
- break;
- }
+ if (has_ongoing_io ())
+ nbytes = (DWORD) -1;
+ else
+ while (1)
+ {
+ bool res = ReadFile (get_handle (), ptr, len, &nbytes,
+ get_overlapped ());
+ int wres = wait_overlapped (res, false, &nbytes);
+ if (wres || !_my_tls.call_signal_handler ())
+ break;
+ }
len = (size_t) nbytes;
}
ssize_t __stdcall
-fhandler_base::write_overlapped (const void *ptr, size_t len)
+fhandler_base_overlapped::write_overlapped (const void *ptr, size_t len)
{
DWORD nbytes;
- while (1)
- {
- bool res = WriteFile (get_output_handle (), ptr, len, &nbytes,
- get_overlapped ());
- int wres = wait_overlapped (res, true, &nbytes, (size_t) len);
- if (wres || !_my_tls.call_signal_handler ())
- break;
- }
+ if (has_ongoing_io ())
+ nbytes = (DWORD) -1;
+ else
+ while (1)
+ {
+ bool res = WriteFile (get_output_handle (), ptr, len, &nbytes,
+ get_overlapped ());
+ int wres = wait_overlapped (res, true, &nbytes, (size_t) len);
+ if (wres || !_my_tls.call_signal_handler ())
+ break;
+ }
debug_printf ("returning %u", nbytes);
return nbytes;
}
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 3d1b46bf4..4fc688531 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -150,9 +150,6 @@ class fhandler_base
void del_my_locks (del_lock_called_from);
HANDLE read_state;
- int wait_overlapped (bool, bool, DWORD *, DWORD = 0) __attribute__ ((regparm (3)));
- bool setup_overlapped (bool doit = true) __attribute__ ((regparm (2)));
- void destroy_overlapped () __attribute__ ((regparm (1)));
public:
class fhandler_base *archetype;
@@ -310,9 +307,7 @@ class fhandler_base
virtual int fcntl (int cmd, void *);
virtual char const *ttyname () { return get_name (); }
virtual void __stdcall read (void *ptr, size_t& len) __attribute__ ((regparm (3)));
- virtual void __stdcall read_overlapped (void *ptr, size_t& len) __attribute__ ((regparm (3)));
virtual ssize_t __stdcall write (const void *ptr, size_t len);
- virtual ssize_t __stdcall write_overlapped (const void *ptr, size_t len);
virtual ssize_t __stdcall readv (const struct iovec *, int iovcnt, ssize_t tot = -1);
virtual ssize_t __stdcall writev (const struct iovec *, int iovcnt, ssize_t tot = -1);
virtual ssize_t __stdcall pread (void *, size_t, _off64_t) __attribute__ ((regparm (3)));
@@ -354,9 +349,6 @@ class fhandler_base
virtual void __stdcall raw_read (void *ptr, size_t& ulen);
virtual ssize_t __stdcall raw_write (const void *ptr, size_t ulen);
- virtual OVERLAPPED *get_overlapped () {return NULL;}
- virtual OVERLAPPED *get_overlapped_buffer () {return NULL;}
- virtual void set_overlapped (OVERLAPPED *) {}
/* Virtual accessor functions to hide the fact
that some fd's have two handles. */
@@ -394,6 +386,8 @@ class fhandler_base
bool issymlink () {return pc.issymlink ();}
bool device_access_denied (int) __attribute__ ((regparm (2)));
int fhaccess (int flags, bool) __attribute__ ((regparm (3)));
+ virtual void destroy_overlapped () __attribute__ ((regparm (1))) {}
+ virtual bool setup_overlapped () {return false;}
};
class fhandler_mailslot : public fhandler_base
@@ -558,18 +552,32 @@ class fhandler_socket: public fhandler_base
bool is_slow () {return true;}
};
-class fhandler_pipe: public fhandler_base
+class fhandler_base_overlapped: public fhandler_base
{
-private:
- pid_t popen_pid;
+protected:
+ bool io_pending;
OVERLAPPED io_status;
OVERLAPPED *overlapped;
public:
- fhandler_pipe ();
-
+ int wait_overlapped (bool, bool, DWORD *, DWORD = 0) __attribute__ ((regparm (3)));
+ bool setup_overlapped (bool doit = true) __attribute__ ((regparm (2)));
+ void destroy_overlapped () __attribute__ ((regparm (1)));
+ void __stdcall read_overlapped (void *ptr, size_t& len) __attribute__ ((regparm (3)));
+ ssize_t __stdcall write_overlapped (const void *ptr, size_t len);
OVERLAPPED *get_overlapped () {return overlapped;}
OVERLAPPED *get_overlapped_buffer () {return &io_status;}
void set_overlapped (OVERLAPPED *ov) {overlapped = ov;}
+ fhandler_base_overlapped (): io_pending (false), overlapped (NULL) {}
+ bool has_ongoing_io ();
+};
+
+class fhandler_pipe: public fhandler_base_overlapped
+{
+private:
+ pid_t popen_pid;
+public:
+ fhandler_pipe ();
+
bool ispipe() const { return true; }
@@ -595,7 +603,7 @@ public:
friend class fhandler_fifo;
};
-class fhandler_fifo: public fhandler_base
+class fhandler_fifo: public fhandler_base_overlapped
{
enum fifo_state
{
@@ -611,7 +619,6 @@ class fhandler_fifo: public fhandler_base
fifo_state wait_state;
HANDLE dummy_client;
HANDLE open_nonserver (const char *, unsigned, LPSECURITY_ATTRIBUTES);
- OVERLAPPED io_status;
bool wait (bool) __attribute__ ((regparm (1)));
char *fifo_name (char *) __attribute__ ((regparm (2)));
public:
@@ -624,8 +631,6 @@ public:
bool isfifo () const { return true; }
void set_close_on_exec (bool val);
int __stdcall fstatvfs (struct statvfs *buf) __attribute__ ((regparm (2)));
- OVERLAPPED *get_overlapped () {return &io_status;}
- OVERLAPPED *get_overlapped_buffer () {return &io_status;}
select_record *select_read (select_stuff *);
select_record *select_write (select_stuff *);
select_record *select_except (select_stuff *);
diff --git a/winsup/cygwin/pipe.cc b/winsup/cygwin/pipe.cc
index 5194856bc..9f3e6fbc4 100644
--- a/winsup/cygwin/pipe.cc
+++ b/winsup/cygwin/pipe.cc
@@ -24,7 +24,7 @@ details. */
#include "shared_info.h"
fhandler_pipe::fhandler_pipe ()
- : fhandler_base (), popen_pid (0), overlapped (NULL)
+ : fhandler_base_overlapped (), popen_pid (0)
{
need_fork_fixup (true);
uninterruptible_io (true);
@@ -378,6 +378,11 @@ pipe (int filedes[2])
{
cygheap_fdnew fdin;
cygheap_fdnew fdout (fdin, false);
+ char buf[sizeof ("/dev/fd/pipe:[2147483647]")];
+ __small_sprintf (buf, "/dev/fd/pipe:[%d]", (int) fdin);
+ fhs[0]->pc.set_normalized_path (buf);
+ __small_sprintf (buf, "pipe:[%d]", (int) fdout);
+ fhs[1]->pc.set_normalized_path (buf);
fdin = fhs[0];
fdout = fhs[1];
filedes[0] = fdin;