* fhandler.h (fhandler_base_setup_overlapped): Add new argument.
(fhandler_base::get_overlapped_buffer): Declare new function. (fhandler_base::set_overlapped): Ditto. (fhandler_pipe::overlapped): New variable. (fhandler_pipe::get_overlapped): Rework to return contents of overlapped variable. (fhandler_pipe::set_overlapped): Set overlapped variable based on argument. (fhandler_fifo::get_overlapped_buffer): Return pointer to io_status. * fhandler.cc (handler_base::setup_overlapped): Set to overlapped pointer to NULL if new doit parameter is false. Otherwise set up overlapped event as usual. (fhandler_base::wait_overlapped): Return inres if this isn't an overlapped operation. (fhandler_base::read_overlapped): Remove inappropriate asserts. * pipe.cc (fhandler_pipe::fhandler_pipe): Zero overlapped element. (struct pipesync): Delete. (getov_result): Ditto. (pipe_handler): Ditto. (pipesync::pipesync): Ditto. (fhandler_pipe::init): Don't set up pipesync thread. Just pass opened_properly flag along to overlapped setup.
This commit is contained in:
		| @@ -1,3 +1,28 @@ | ||||
| 2008-12-23  Christopher Faylor  <me+cygwin@cgf.cx> | ||||
|  | ||||
| 	* fhandler.h (fhandler_base_setup_overlapped): Add new argument. | ||||
| 	(fhandler_base::get_overlapped_buffer): Declare new function. | ||||
| 	(fhandler_base::set_overlapped): Ditto. | ||||
| 	(fhandler_pipe::overlapped): New variable. | ||||
| 	(fhandler_pipe::get_overlapped): Rework to return contents of | ||||
| 	overlapped variable. | ||||
| 	(fhandler_pipe::set_overlapped): Set overlapped variable based on | ||||
| 	argument. | ||||
| 	(fhandler_fifo::get_overlapped_buffer): Return pointer to io_status. | ||||
| 	* fhandler.cc (handler_base::setup_overlapped): Set to overlapped | ||||
| 	pointer to NULL if new doit parameter is false.  Otherwise set up | ||||
| 	overlapped event as usual. | ||||
| 	(fhandler_base::wait_overlapped): Return inres if this isn't an | ||||
| 	overlapped operation. | ||||
| 	(fhandler_base::read_overlapped): Remove inappropriate asserts. | ||||
| 	* pipe.cc (fhandler_pipe::fhandler_pipe): Zero overlapped element. | ||||
| 	(struct pipesync): Delete. | ||||
| 	(getov_result): Ditto. | ||||
| 	(pipe_handler): Ditto. | ||||
| 	(pipesync::pipesync): Ditto. | ||||
| 	(fhandler_pipe::init): Don't set up pipesync thread.  Just pass | ||||
| 	opened_properly flag along to overlapped setup. | ||||
|  | ||||
| 2008-12-22  Christopher Faylor  <me+cygwin@cgf.cx> | ||||
|  | ||||
| 	* pipe.cc (getov_result): Minor cleanup. | ||||
| @@ -66,7 +91,7 @@ | ||||
| 2008-12-18  Corinna Vinschen  <corinna@vinschen.de> | ||||
|  | ||||
| 	* fhandler_disk_file.cc: Set 4th parameter of NtQueryDirectoryFile to | ||||
| 	NULL throughout.   | ||||
| 	NULL throughout. | ||||
| 	(fhandler_disk_file::facl): Fix a condition so that fstat_by_handle | ||||
| 	is actually used. | ||||
| 	(fhandler_disk_file::readdir): Don't print debug message on a simple | ||||
|   | ||||
| @@ -1661,11 +1661,22 @@ fhandler_base::fpathconf (int v) | ||||
| /* Overlapped I/O */ | ||||
|  | ||||
| bool | ||||
| fhandler_base::setup_overlapped () | ||||
| fhandler_base::setup_overlapped (bool doit) | ||||
| { | ||||
|   OVERLAPPED *ov = get_overlapped (); | ||||
|   OVERLAPPED *ov = get_overlapped_buffer (); | ||||
|   memset (ov, 0, sizeof (*ov)); | ||||
|   return (ov->hEvent = CreateEvent (&sec_none_nih, true, false, NULL)); | ||||
|   bool res; | ||||
|   if (doit) | ||||
|     { | ||||
|       set_overlapped (ov); | ||||
|       res = !!(ov->hEvent = CreateEvent (&sec_none_nih, true, false, NULL)); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       set_overlapped (NULL); | ||||
|       res = false; | ||||
|     } | ||||
|   return res; | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -1682,6 +1693,9 @@ fhandler_base::destroy_overlapped () | ||||
| int | ||||
| fhandler_base::wait_overlapped (bool inres, bool writing, DWORD *bytes) | ||||
| { | ||||
|   if (!get_overlapped ()) | ||||
|     return inres; | ||||
|  | ||||
|   int res = 0; | ||||
|   *bytes = (DWORD) -1; | ||||
|   DWORD err; | ||||
| @@ -1753,10 +1767,6 @@ fhandler_base::wait_overlapped (bool inres, bool writing, DWORD *bytes) | ||||
| void | ||||
| fhandler_base::read_overlapped (void *ptr, size_t& len) | ||||
| { | ||||
| #ifdef DEBUGGING | ||||
|   assert (get_overlapped ()); | ||||
|   assert (get_overlapped ()->hEvent); | ||||
| #endif | ||||
|   while (1) | ||||
|     { | ||||
|       bool res = ReadFile (get_handle (), ptr, len, (DWORD *) &len, | ||||
|   | ||||
| @@ -144,7 +144,7 @@ class fhandler_base | ||||
|  | ||||
|   HANDLE read_state; | ||||
|   int wait_overlapped (bool, bool, DWORD *) __attribute__ ((regparm (3))); | ||||
|   bool setup_overlapped () __attribute__ ((regparm (1))); | ||||
|   bool setup_overlapped (bool doit = true) __attribute__ ((regparm (2))); | ||||
|   void destroy_overlapped () __attribute__ ((regparm (1))); | ||||
|  | ||||
|  public: | ||||
| @@ -344,6 +344,8 @@ class fhandler_base | ||||
|   virtual void raw_read (void *ptr, size_t& ulen); | ||||
|   virtual int 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. */ | ||||
| @@ -532,9 +534,14 @@ class fhandler_pipe: public fhandler_base | ||||
| private: | ||||
|   pid_t popen_pid; | ||||
|   OVERLAPPED io_status; | ||||
|   OVERLAPPED *overlapped; | ||||
| public: | ||||
|   fhandler_pipe (); | ||||
|   OVERLAPPED *get_overlapped () {return &io_status;} | ||||
|  | ||||
|   OVERLAPPED *get_overlapped () {return overlapped;} | ||||
|   OVERLAPPED *get_overlapped_buffer () {return &io_status;} | ||||
|   void set_overlapped (OVERLAPPED *ov) {overlapped = ov;} | ||||
|  | ||||
|   void set_popen_pid (pid_t pid) {popen_pid = pid;} | ||||
|   pid_t get_popen_pid () const {return popen_pid;} | ||||
|   _off64_t lseek (_off64_t offset, int whence); | ||||
| @@ -577,6 +584,7 @@ public: | ||||
|   bool isfifo () { return true; } | ||||
|   int __stdcall fstatvfs (struct statvfs *buf) __attribute__ ((regparm (2))); | ||||
|   OVERLAPPED *get_overlapped () {return &io_status;} | ||||
|   OVERLAPPED *get_overlapped_buffer () {return &io_status;} | ||||
| }; | ||||
|  | ||||
| class fhandler_dev_raw: public fhandler_base | ||||
|   | ||||
| @@ -23,136 +23,11 @@ details. */ | ||||
| #include "pinfo.h" | ||||
|  | ||||
| fhandler_pipe::fhandler_pipe () | ||||
|   : fhandler_base (), popen_pid (0) | ||||
|   : fhandler_base (), popen_pid (0), overlapped (NULL) | ||||
| { | ||||
|   get_overlapped ()->hEvent = NULL; | ||||
|   need_fork_fixup (true); | ||||
| } | ||||
|  | ||||
| struct pipesync | ||||
| { | ||||
|   bool reader; | ||||
|   HANDLE ev, non_cygwin_h, ret_handle; | ||||
|   pipesync(HANDLE, DWORD); | ||||
|   int operator == (int x) const {return !!ev;} | ||||
|   static DWORD WINAPI handler (LPVOID *); | ||||
| }; | ||||
|  | ||||
| inline bool | ||||
| getov_result (BOOL res, bool reading, HANDLE h, DWORD& nbytes, LPOVERLAPPED ov) | ||||
| { | ||||
|   DWORD err = GetLastError (); | ||||
|   if (res || (reading && ov && err == ERROR_HANDLE_EOF)) | ||||
|     /* not an error */; | ||||
|   else if (!ov || (err != ERROR_IO_PENDING) | ||||
| 	   || (!GetOverlappedResult (h, ov, &nbytes, true) | ||||
| 	       && (!reading || (GetLastError () != ERROR_HANDLE_EOF)))) | ||||
|     { | ||||
|       __seterrno (); | ||||
|       return false; | ||||
|     } | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| static DWORD WINAPI | ||||
| pipe_handler (LPVOID in_ps) | ||||
| { | ||||
|   pipesync ps = *(pipesync *) in_ps; | ||||
|   HANDLE h, in, out; | ||||
|   DWORD err = fhandler_pipe::create_selectable (&sec_none_nih, in, out, 0); | ||||
|   if (err) | ||||
|     { | ||||
|       SetLastError (err); | ||||
|       system_printf ("couldn't create a shadow pipe for non-cygwin pipe I/O, %E"); | ||||
|       return 0; | ||||
|     } | ||||
|   h = ((pipesync *) in_ps)->ret_handle = ps.reader ? in : out; | ||||
|   SetHandleInformation (h, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); | ||||
|   SetEvent (ps.ev); | ||||
|  | ||||
|   DWORD read_bytes, write_bytes; | ||||
|   HANDLE hread, hwrite, hclose; | ||||
|   OVERLAPPED ov, *rov, *wov; | ||||
|   memset (&ov, 0, sizeof (ov)); | ||||
|   ov.hEvent = CreateEvent (&sec_none_nih, true, false, NULL); | ||||
|   if (ps.reader) | ||||
|     { | ||||
|       hread = ps.non_cygwin_h; | ||||
|       hclose = hwrite = out; | ||||
|       wov = &ov; | ||||
|       rov = NULL; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       hclose = hread = in; | ||||
|       hwrite = ps.non_cygwin_h; | ||||
|       rov = &ov; | ||||
|       wov = NULL; | ||||
|     } | ||||
|  | ||||
|   char buf[4096]; | ||||
|   while (1) | ||||
|     { | ||||
|       ResetEvent (ov.hEvent); | ||||
|       BOOL res = ReadFile (hread, buf, 4096, &read_bytes, rov); | ||||
|       if (!getov_result (res, true, hread, read_bytes, rov)) | ||||
| 	break; | ||||
|       if (!read_bytes) | ||||
| 	break; | ||||
|  | ||||
|       res = WriteFile (hwrite, buf, read_bytes, &write_bytes, wov); | ||||
|       if (!getov_result (res, false, hwrite, write_bytes, wov)) | ||||
| 	break; | ||||
|       if (write_bytes != read_bytes) | ||||
| 	break; | ||||
|     } | ||||
|  | ||||
|   err = GetLastError (); | ||||
|   CloseHandle (ov.hEvent); | ||||
|   CloseHandle (hclose); | ||||
|   CloseHandle (ps.non_cygwin_h); | ||||
|   SetLastError (err); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| pipesync::pipesync (HANDLE f, DWORD is_reader): | ||||
|   reader (false), ret_handle (NULL) | ||||
| { | ||||
|   ev = CreateEvent (&sec_none_nih, true, false, NULL); | ||||
|   if (!ev) | ||||
|     system_printf ("couldn't create synchronization event for non-cygwin pipe, %E"); | ||||
|   else | ||||
|     { | ||||
|       debug_printf ("created thread synchronization event %p", ev); | ||||
|       non_cygwin_h = f; | ||||
|       reader = !!is_reader; | ||||
|       ret_handle = NULL; | ||||
|  | ||||
|       DWORD tid; | ||||
|       HANDLE ht = CreateThread (&sec_none_nih, 0, pipe_handler, this, 0, &tid); | ||||
|  | ||||
|       if (!ht) | ||||
| 	goto out; | ||||
|       CloseHandle (ht); | ||||
|  | ||||
|       switch (WaitForSingleObject (ev, INFINITE)) | ||||
| 	{ | ||||
| 	case WAIT_OBJECT_0: | ||||
| 	  break; | ||||
| 	default: | ||||
| 	  system_printf ("WFSO failed waiting for synchronization event for non-cygwin pipe, %E"); | ||||
| 	  break; | ||||
| 	} | ||||
|     } | ||||
|  | ||||
| out: | ||||
|   if (ev) | ||||
|     { | ||||
|       CloseHandle (ev); | ||||
|       ev = NULL; | ||||
|     } | ||||
| } | ||||
|  | ||||
| void | ||||
| fhandler_pipe::init (HANDLE f, DWORD a, mode_t mode) | ||||
| { | ||||
| @@ -173,16 +48,10 @@ fhandler_pipe::init (HANDLE f, DWORD a, mode_t mode) | ||||
|  | ||||
|   bool opened_properly = a & FILE_CREATE_PIPE_INSTANCE; | ||||
|   a &= ~FILE_CREATE_PIPE_INSTANCE; | ||||
|   if (!opened_properly) | ||||
|     { | ||||
|       pipesync ps (f, a & GENERIC_READ); | ||||
|       f = ps.ret_handle; | ||||
|     } | ||||
|  | ||||
|   fhandler_base::init (f, a, mode); | ||||
|   if (mode & O_NOINHERIT) | ||||
|     close_on_exec (true); | ||||
|   setup_overlapped (); | ||||
|   setup_overlapped (opened_properly); | ||||
| } | ||||
|  | ||||
| extern "C" int sscanf (const char *, const char *, ...); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user