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 + + * 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 * 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;