Fix OPOST for non-Cygwin pty slaves
* fhandler.h (class fhandler_base): Add virtual function get_io_handle_cyg() to get handle from which OPOST-processed output is read on PTY master. (class fhandler_pty_slave): Add variable output_handle_cyg to store a handle to which OPOST-processed output is written. Add two functions, i.e., set_output_handle_cyg() and get_output_handle_cyg(), regarding variable output_handle_cyg. Now, output_handle is used only by native windows program. The data before OPOST-processing is written to output_handle and OPOST-processing is applied in the master-side. For a cygwin process, OPOST-processing is applied in the slave-side, and the data after OPOST-processing is written to output_handle_cyg. (class fhandler_pty_master): Add two variables, i.e., io_handle_cyg and to_master_cyg, to store handles of a pipe through which OPOST-processed output passes. Add pty_master_fwd_thread and function pty_master_fwd_thread() for a thread which applies OPOST-processing and forwards data from io_handle to to_master_cyg. Add function get_io_handle_cyg() regarding variable io_handle_cyg. Now, the pipe between io_handle and to_master are used only by native windows program for applying OPOST-processing in the master-side. For a cygwin process, the pipe between io_handle_cyg and to_master_cyg is used for passing through the data which is applied OPOST-processing in the slave-side. * fhandler_tty.cc (struct pipe_reply): Add member to_master_cyg. (fhandler_pty_master::process_slave_output): Read slave output from io_handle_cyg rather than io_handle. (fhandler_pty_slave::fhandler_pty_salve): Initialize output_handle_cyg. (fhandler_pty_slave::open): Set output_handle_cyg by duplicating handle to_master_cyg on PTY master. (fhandler_pty_slave::close): Close handle output_handle_cyg. (fhandler_pty_slave::write): Write data to output_handle_cyg rather than output_handle. (fhandler_pty_slave::fch_close_handles): Close handle output_handle_cyg. (fhandler_pty_master::fhandler_pty_master): Initialize io_handle_cyg, to_master_cyg and master_fwd_thread. (fhandler_pty_master::cleanup): Clean up to_master_cyg as well. (fhandler_pty_master::close): Print to_master_cyg as well in debug message. Terminate master forwarding thread. Close handles to_master_cyg and io_handle_cyg. (fhandler_pty_master::ioctl): Use io_handle_cyg rather than to_master. (fhandler_pty_master::pty_master_thread): Add code for duplicating handle to_master_cyg. (fhandler_pty_master::pty_master_fwd_thread): New function for a thread to forward OPOST-processed data from io_handle to to_master_cyg. This thread applies OPOST-processing to the output of native windows program. (::pty_master_fwd_thread): Ditto. (fhandler_pty_master::setup): Create a new pipe to pass thruegh OPOST- processed output. Create new thread to forward data from io_handle to to_master_cyg. Set handle to_master_cyg to tty. Print io_handle_cyg as well in debug message. Close handles io_handle_cyg and to_master_cyg in case of error. (fhandler_pty_master::fixup_after_fork): Set handle to_master_cyg to tty. Copy handle to_master_cyg from arch->to_master_cyg. (fhandler_pty_master::fixup_after_exec): Clean up to_master_cyg. * select.cc: Check handle returned by get_io_handle_cyg() rather than get_handle(). * tty.h (class tty): Add variable _to_master_cyg to store a handle to which OPOST-processed data is written. Add two functions, to_master_cyg() and set_to_master_cyg(), regarding _to_master_cyg. Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
		
				
					committed by
					
						 Corinna Vinschen
						Corinna Vinschen
					
				
			
			
				
	
			
			
			
						parent
						
							6d099d5bae
						
					
				
				
					commit
					c846bca992
				
			| @@ -1,3 +1,63 @@ | |||||||
|  | 2015-04-22  Takashi Yano  <takashi.yano@nifty.ne.jp> | ||||||
|  |  | ||||||
|  | 	* fhandler.h (class fhandler_base): Add virtual function | ||||||
|  | 	get_io_handle_cyg() to get handle from which OPOST-processed output is | ||||||
|  | 	read on PTY master. | ||||||
|  | 	(class fhandler_pty_slave): Add variable output_handle_cyg to store a | ||||||
|  | 	handle to which OPOST-processed output is written. Add two functions, | ||||||
|  | 	i.e., set_output_handle_cyg() and get_output_handle_cyg(), regarding | ||||||
|  | 	variable output_handle_cyg. Now, output_handle is used only by native | ||||||
|  | 	windows program. The data before OPOST-processing is written to | ||||||
|  | 	output_handle and OPOST-processing is applied in the master-side. For a | ||||||
|  | 	cygwin process, OPOST-processing is applied in the slave-side, and the | ||||||
|  | 	data after OPOST-processing is written to output_handle_cyg. | ||||||
|  | 	(class fhandler_pty_master): Add two variables, i.e., io_handle_cyg and | ||||||
|  | 	to_master_cyg, to store handles of a pipe through which OPOST-processed | ||||||
|  | 	output passes. Add pty_master_fwd_thread and function | ||||||
|  | 	pty_master_fwd_thread() for a thread which applies OPOST-processing | ||||||
|  | 	and forwards data from io_handle to to_master_cyg. Add function | ||||||
|  | 	get_io_handle_cyg() regarding variable io_handle_cyg. Now, the pipe | ||||||
|  | 	between io_handle and to_master are used only by native windows program | ||||||
|  | 	for applying OPOST-processing in the master-side. For a cygwin process, | ||||||
|  | 	the pipe between io_handle_cyg and to_master_cyg is used for passing | ||||||
|  | 	through the data which is applied OPOST-processing in the slave-side. | ||||||
|  | 	* fhandler_tty.cc (struct pipe_reply): Add member to_master_cyg. | ||||||
|  | 	(fhandler_pty_master::process_slave_output): Read slave output from | ||||||
|  | 	io_handle_cyg rather than io_handle. | ||||||
|  | 	(fhandler_pty_slave::fhandler_pty_salve): Initialize output_handle_cyg. | ||||||
|  | 	(fhandler_pty_slave::open): Set output_handle_cyg by duplicating handle | ||||||
|  | 	to_master_cyg on PTY master. | ||||||
|  | 	(fhandler_pty_slave::close): Close handle output_handle_cyg. | ||||||
|  | 	(fhandler_pty_slave::write): Write data to output_handle_cyg rather | ||||||
|  | 	than output_handle. | ||||||
|  | 	(fhandler_pty_slave::fch_close_handles): Close handle output_handle_cyg. | ||||||
|  | 	(fhandler_pty_master::fhandler_pty_master): Initialize io_handle_cyg, | ||||||
|  | 	to_master_cyg and master_fwd_thread. | ||||||
|  | 	(fhandler_pty_master::cleanup): Clean up to_master_cyg as well. | ||||||
|  | 	(fhandler_pty_master::close): Print to_master_cyg as well in debug | ||||||
|  | 	message. Terminate master forwarding thread. Close handles | ||||||
|  | 	to_master_cyg and io_handle_cyg. | ||||||
|  | 	(fhandler_pty_master::ioctl): Use io_handle_cyg rather than to_master. | ||||||
|  | 	(fhandler_pty_master::pty_master_thread): Add code for duplicating | ||||||
|  | 	handle to_master_cyg. | ||||||
|  | 	(fhandler_pty_master::pty_master_fwd_thread): New function for a thread | ||||||
|  | 	to forward OPOST-processed data from io_handle to to_master_cyg.  This | ||||||
|  | 	thread applies OPOST-processing to the output of native windows program. | ||||||
|  | 	(::pty_master_fwd_thread): Ditto. | ||||||
|  | 	(fhandler_pty_master::setup): Create a new pipe to pass thruegh OPOST- | ||||||
|  | 	processed output. Create new thread to forward data from io_handle to | ||||||
|  | 	to_master_cyg. Set handle to_master_cyg to tty. Print io_handle_cyg as | ||||||
|  | 	well in debug message. Close handles io_handle_cyg and to_master_cyg in | ||||||
|  | 	case of error. | ||||||
|  | 	(fhandler_pty_master::fixup_after_fork): Set handle to_master_cyg to | ||||||
|  | 	tty. Copy handle to_master_cyg from arch->to_master_cyg. | ||||||
|  | 	(fhandler_pty_master::fixup_after_exec): Clean up to_master_cyg. | ||||||
|  | 	* select.cc: Check handle returned by get_io_handle_cyg() rather than | ||||||
|  | 	get_handle(). | ||||||
|  | 	* tty.h (class tty): Add variable _to_master_cyg to store a handle to | ||||||
|  | 	which OPOST-processed data is written. Add two functions, | ||||||
|  | 	to_master_cyg() and set_to_master_cyg(), regarding _to_master_cyg. | ||||||
|  |  | ||||||
| 2015-04-22  Corinna Vinschen  <corinna@vinschen.de> | 2015-04-22  Corinna Vinschen  <corinna@vinschen.de> | ||||||
|  |  | ||||||
| 	* path.cc (basename): Undefine basename before defining function to | 	* path.cc (basename): Undefine basename before defining function to | ||||||
|   | |||||||
| @@ -412,6 +412,7 @@ public: | |||||||
|      that some fd's have two handles. */ |      that some fd's have two handles. */ | ||||||
|   virtual HANDLE& get_handle () { return io_handle; } |   virtual HANDLE& get_handle () { return io_handle; } | ||||||
|   virtual HANDLE& get_io_handle () { return io_handle; } |   virtual HANDLE& get_io_handle () { return io_handle; } | ||||||
|  |   virtual HANDLE& get_io_handle_cyg () { return io_handle; } | ||||||
|   virtual HANDLE& get_output_handle () { return io_handle; } |   virtual HANDLE& get_output_handle () { return io_handle; } | ||||||
|   virtual HANDLE get_stat_handle () { return pc.handle () ?: io_handle; } |   virtual HANDLE get_stat_handle () { return pc.handle () ?: io_handle; } | ||||||
|   virtual HANDLE get_echo_handle () const { return NULL; } |   virtual HANDLE get_echo_handle () const { return NULL; } | ||||||
| @@ -1516,6 +1517,7 @@ class fhandler_pty_common: public fhandler_termios | |||||||
| class fhandler_pty_slave: public fhandler_pty_common | class fhandler_pty_slave: public fhandler_pty_common | ||||||
| { | { | ||||||
|   HANDLE inuse;			// used to indicate that a tty is in use |   HANDLE inuse;			// used to indicate that a tty is in use | ||||||
|  |   HANDLE output_handle_cyg; | ||||||
|  |  | ||||||
|   /* Helper functions for fchmod and fchown. */ |   /* Helper functions for fchmod and fchown. */ | ||||||
|   bool fch_open_handles (bool chown); |   bool fch_open_handles (bool chown); | ||||||
| @@ -1526,6 +1528,9 @@ class fhandler_pty_slave: public fhandler_pty_common | |||||||
|   /* Constructor */ |   /* Constructor */ | ||||||
|   fhandler_pty_slave (int); |   fhandler_pty_slave (int); | ||||||
|  |  | ||||||
|  |   void set_output_handle_cyg (HANDLE h) { output_handle_cyg = h; } | ||||||
|  |   HANDLE& get_output_handle_cyg () { return output_handle_cyg; } | ||||||
|  |  | ||||||
|   int open (int flags, mode_t mode = 0); |   int open (int flags, mode_t mode = 0); | ||||||
|   void open_setup (int flags); |   void open_setup (int flags); | ||||||
|   ssize_t __stdcall write (const void *ptr, size_t len); |   ssize_t __stdcall write (const void *ptr, size_t len); | ||||||
| @@ -1575,13 +1580,17 @@ class fhandler_pty_master: public fhandler_pty_common | |||||||
|   HANDLE from_master, to_master; |   HANDLE from_master, to_master; | ||||||
|   HANDLE echo_r, echo_w; |   HANDLE echo_r, echo_w; | ||||||
|   DWORD dwProcessId;		// Owner of master handles |   DWORD dwProcessId;		// Owner of master handles | ||||||
|  |   HANDLE io_handle_cyg, to_master_cyg; | ||||||
|  |   cygthread *master_fwd_thread;	// Master forwarding thread | ||||||
|  |  | ||||||
| public: | public: | ||||||
|   HANDLE get_echo_handle () const { return echo_r; } |   HANDLE get_echo_handle () const { return echo_r; } | ||||||
|  |   HANDLE& get_io_handle_cyg () { return io_handle_cyg; } | ||||||
|   /* Constructor */ |   /* Constructor */ | ||||||
|   fhandler_pty_master (int); |   fhandler_pty_master (int); | ||||||
|  |  | ||||||
|   DWORD pty_master_thread (); |   DWORD pty_master_thread (); | ||||||
|  |   DWORD pty_master_fwd_thread (); | ||||||
|   int process_slave_output (char *buf, size_t len, int pktmode_on); |   int process_slave_output (char *buf, size_t len, int pktmode_on); | ||||||
|   void doecho (const void *str, DWORD len); |   void doecho (const void *str, DWORD len); | ||||||
|   int accept_input (); |   int accept_input (); | ||||||
|   | |||||||
| @@ -42,6 +42,7 @@ struct pipe_request { | |||||||
| struct pipe_reply { | struct pipe_reply { | ||||||
|   HANDLE from_master; |   HANDLE from_master; | ||||||
|   HANDLE to_master; |   HANDLE to_master; | ||||||
|  |   HANDLE to_master_cyg; | ||||||
|   DWORD error; |   DWORD error; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -236,7 +237,7 @@ fhandler_pty_master::process_slave_output (char *buf, size_t len, int pktmode_on | |||||||
| 	  /* Check echo pipe first. */ | 	  /* Check echo pipe first. */ | ||||||
| 	  if (::bytes_available (echo_cnt, echo_r) && echo_cnt > 0) | 	  if (::bytes_available (echo_cnt, echo_r) && echo_cnt > 0) | ||||||
| 	    break; | 	    break; | ||||||
| 	  if (!bytes_available (n)) | 	  if (!::bytes_available (n, get_io_handle_cyg ())) | ||||||
| 	    goto err; | 	    goto err; | ||||||
| 	  if (n) | 	  if (n) | ||||||
| 	    break; | 	    break; | ||||||
| @@ -297,7 +298,7 @@ fhandler_pty_master::process_slave_output (char *buf, size_t len, int pktmode_on | |||||||
| 	      goto err; | 	      goto err; | ||||||
| 	    } | 	    } | ||||||
| 	} | 	} | ||||||
|       else if (!ReadFile (get_handle (), outbuf, rlen, &n, NULL)) |       else if (!ReadFile (get_io_handle_cyg (), outbuf, rlen, &n, NULL)) | ||||||
| 	{ | 	{ | ||||||
| 	  termios_printf ("ReadFile failed, %E"); | 	  termios_printf ("ReadFile failed, %E"); | ||||||
| 	  goto err; | 	  goto err; | ||||||
| @@ -332,7 +333,7 @@ out: | |||||||
| /* pty slave stuff */ | /* pty slave stuff */ | ||||||
|  |  | ||||||
| fhandler_pty_slave::fhandler_pty_slave (int unit) | fhandler_pty_slave::fhandler_pty_slave (int unit) | ||||||
|   : fhandler_pty_common (), inuse (NULL) |   : fhandler_pty_common (), inuse (NULL), output_handle_cyg (NULL) | ||||||
| { | { | ||||||
|   if (unit >= 0) |   if (unit >= 0) | ||||||
|     dev ().parse (DEV_PTYS_MAJOR, unit); |     dev ().parse (DEV_PTYS_MAJOR, unit); | ||||||
| @@ -341,11 +342,11 @@ fhandler_pty_slave::fhandler_pty_slave (int unit) | |||||||
| int | int | ||||||
| fhandler_pty_slave::open (int flags, mode_t) | fhandler_pty_slave::open (int flags, mode_t) | ||||||
| { | { | ||||||
|   HANDLE pty_owner, from_master_local, to_master_local; |   HANDLE pty_owner, from_master_local, to_master_local, to_master_cyg_local; | ||||||
|   HANDLE *handles[] = |   HANDLE *handles[] = | ||||||
|   { |   { | ||||||
|     &from_master_local, &input_available_event, &input_mutex, &inuse, |     &from_master_local, &input_available_event, &input_mutex, &inuse, | ||||||
|     &output_mutex, &to_master_local, &pty_owner, |     &output_mutex, &to_master_local, &pty_owner, &to_master_cyg_local, | ||||||
|     NULL |     NULL | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
| @@ -397,7 +398,8 @@ fhandler_pty_slave::open (int flags, mode_t) | |||||||
|     release_output_mutex (); |     release_output_mutex (); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (!get_ttyp ()->from_master () || !get_ttyp ()->to_master ()) |   if (!get_ttyp ()->from_master () || | ||||||
|  |       !get_ttyp ()->to_master () || !get_ttyp ()->to_master_cyg ()) | ||||||
|     { |     { | ||||||
|       errmsg = "pty handles have been closed"; |       errmsg = "pty handles have been closed"; | ||||||
|       set_errno (EACCES); |       set_errno (EACCES); | ||||||
| @@ -448,6 +450,13 @@ fhandler_pty_slave::open (int flags, mode_t) | |||||||
| 	  errmsg = "can't duplicate output, %E"; | 	  errmsg = "can't duplicate output, %E"; | ||||||
| 	  goto err; | 	  goto err; | ||||||
| 	} | 	} | ||||||
|  |       if (!DuplicateHandle (pty_owner, get_ttyp ()->to_master_cyg (), | ||||||
|  | 			  GetCurrentProcess (), &to_master_cyg_local, 0, TRUE, | ||||||
|  | 			  DUPLICATE_SAME_ACCESS)) | ||||||
|  | 	{ | ||||||
|  | 	  errmsg = "can't duplicate output for cygwin, %E"; | ||||||
|  | 	  goto err; | ||||||
|  | 	} | ||||||
|       if (pty_owner != GetCurrentProcess ()) |       if (pty_owner != GetCurrentProcess ()) | ||||||
| 	CloseHandle (pty_owner); | 	CloseHandle (pty_owner); | ||||||
|     } |     } | ||||||
| @@ -468,7 +477,8 @@ fhandler_pty_slave::open (int flags, mode_t) | |||||||
| 	} | 	} | ||||||
|       from_master_local = repl.from_master; |       from_master_local = repl.from_master; | ||||||
|       to_master_local = repl.to_master; |       to_master_local = repl.to_master; | ||||||
|       if (!from_master_local || !to_master_local) |       to_master_cyg_local = repl.to_master_cyg; | ||||||
|  |       if (!from_master_local || !to_master_local || !to_master_cyg_local) | ||||||
| 	{ | 	{ | ||||||
| 	  SetLastError (repl.error); | 	  SetLastError (repl.error); | ||||||
| 	  errmsg = "error duplicating pipes, %E"; | 	  errmsg = "error duplicating pipes, %E"; | ||||||
| @@ -477,14 +487,18 @@ fhandler_pty_slave::open (int flags, mode_t) | |||||||
|     } |     } | ||||||
|   VerifyHandle (from_master_local); |   VerifyHandle (from_master_local); | ||||||
|   VerifyHandle (to_master_local); |   VerifyHandle (to_master_local); | ||||||
|  |   VerifyHandle (to_master_cyg_local); | ||||||
|  |  | ||||||
|   termios_printf ("duplicated from_master %p->%p from pty_owner", |   termios_printf ("duplicated from_master %p->%p from pty_owner", | ||||||
| 		  get_ttyp ()->from_master (), from_master_local); | 		  get_ttyp ()->from_master (), from_master_local); | ||||||
|   termios_printf ("duplicated to_master %p->%p from pty_owner", |   termios_printf ("duplicated to_master %p->%p from pty_owner", | ||||||
| 		  get_ttyp ()->to_master (), to_master_local); | 		  get_ttyp ()->to_master (), to_master_local); | ||||||
|  |   termios_printf ("duplicated to_master_cyg %p->%p from pty_owner", | ||||||
|  | 		  get_ttyp ()->to_master_cyg (), to_master_cyg_local); | ||||||
|  |  | ||||||
|   set_io_handle (from_master_local); |   set_io_handle (from_master_local); | ||||||
|   set_output_handle (to_master_local); |   set_output_handle (to_master_local); | ||||||
|  |   set_output_handle_cyg (to_master_cyg_local); | ||||||
|  |  | ||||||
|   fhandler_console::need_invisible (); |   fhandler_console::need_invisible (); | ||||||
|   set_open_status (); |   set_open_status (); | ||||||
| @@ -533,6 +547,9 @@ fhandler_pty_slave::close () | |||||||
|     termios_printf ("CloseHandle (inuse), %E"); |     termios_printf ("CloseHandle (inuse), %E"); | ||||||
|   if (!ForceCloseHandle (input_available_event)) |   if (!ForceCloseHandle (input_available_event)) | ||||||
|     termios_printf ("CloseHandle (input_available_event<%p>), %E", input_available_event); |     termios_printf ("CloseHandle (input_available_event<%p>), %E", input_available_event); | ||||||
|  |   if (!ForceCloseHandle (get_output_handle_cyg ())) | ||||||
|  |     termios_printf ("CloseHandle (get_output_handle_cyg ()<%p>), %E", | ||||||
|  | 	get_output_handle_cyg ()); | ||||||
|   if ((unsigned) myself->ctty == FHDEV (DEV_PTYS_MAJOR, get_minor ())) |   if ((unsigned) myself->ctty == FHDEV (DEV_PTYS_MAJOR, get_minor ())) | ||||||
|     fhandler_console::free_console ();	/* assumes that we are the last pty closer */ |     fhandler_console::free_console ();	/* assumes that we are the last pty closer */ | ||||||
|   return fhandler_pty_common::close (); |   return fhandler_pty_common::close (); | ||||||
| @@ -591,7 +608,7 @@ fhandler_pty_slave::write (const void *ptr, size_t len) | |||||||
|  |  | ||||||
|   push_process_state process_state (PID_TTYOU); |   push_process_state process_state (PID_TTYOU); | ||||||
|  |  | ||||||
|   if (!process_opost_output (get_output_handle (), ptr, towrite, false)) |   if (!process_opost_output (get_output_handle_cyg (), ptr, towrite, false)) | ||||||
|     { |     { | ||||||
|       DWORD err = GetLastError (); |       DWORD err = GetLastError (); | ||||||
|       termios_printf ("WriteFile failed, %E"); |       termios_printf ("WriteFile failed, %E"); | ||||||
| @@ -1069,6 +1086,7 @@ fhandler_pty_slave::fch_close_handles () | |||||||
| { | { | ||||||
|   close_maybe (get_io_handle ()); |   close_maybe (get_io_handle ()); | ||||||
|   close_maybe (get_output_handle ()); |   close_maybe (get_output_handle ()); | ||||||
|  |   close_maybe (get_output_handle_cyg ()); | ||||||
|   close_maybe (input_available_event); |   close_maybe (input_available_event); | ||||||
|   close_maybe (output_mutex); |   close_maybe (output_mutex); | ||||||
|   close_maybe (input_mutex); |   close_maybe (input_mutex); | ||||||
| @@ -1142,7 +1160,8 @@ errout: | |||||||
| fhandler_pty_master::fhandler_pty_master (int unit) | fhandler_pty_master::fhandler_pty_master (int unit) | ||||||
|   : fhandler_pty_common (), pktmode (0), master_ctl (NULL), |   : fhandler_pty_common (), pktmode (0), master_ctl (NULL), | ||||||
|     master_thread (NULL), from_master (NULL), to_master (NULL), |     master_thread (NULL), from_master (NULL), to_master (NULL), | ||||||
|     echo_r (NULL), echo_w (NULL), dwProcessId (0) |     echo_r (NULL), echo_w (NULL), dwProcessId (0), | ||||||
|  |     io_handle_cyg (NULL), to_master_cyg (NULL), master_fwd_thread (NULL) | ||||||
| { | { | ||||||
|   if (unit >= 0) |   if (unit >= 0) | ||||||
|     dev ().parse (DEV_PTYM_MAJOR, unit); |     dev ().parse (DEV_PTYM_MAJOR, unit); | ||||||
| @@ -1200,15 +1219,15 @@ fhandler_pty_master::cleanup () | |||||||
| { | { | ||||||
|   report_tty_counts (this, "closing master", ""); |   report_tty_counts (this, "closing master", ""); | ||||||
|   if (archetype) |   if (archetype) | ||||||
|     from_master = to_master = NULL; |     from_master = to_master = to_master_cyg = NULL; | ||||||
|   fhandler_base::cleanup (); |   fhandler_base::cleanup (); | ||||||
| } | } | ||||||
|  |  | ||||||
| int | int | ||||||
| fhandler_pty_master::close () | fhandler_pty_master::close () | ||||||
| { | { | ||||||
|   termios_printf ("closing from_master(%p)/to_master(%p) since we own them(%u)", |   termios_printf ("closing from_master(%p)/to_master(%p)/to_master_cyg(%p) since we own them(%u)", | ||||||
| 		  from_master, to_master, dwProcessId); | 		  from_master, to_master, to_master_cyg, dwProcessId); | ||||||
|   if (cygwin_finished_initializing) |   if (cygwin_finished_initializing) | ||||||
|     { |     { | ||||||
|       if (master_ctl && get_ttyp ()->master_pid == myself->pid) |       if (master_ctl && get_ttyp ()->master_pid == myself->pid) | ||||||
| @@ -1231,6 +1250,7 @@ fhandler_pty_master::close () | |||||||
| 	      master_ctl = NULL; | 	      master_ctl = NULL; | ||||||
| 	    } | 	    } | ||||||
| 	  release_output_mutex (); | 	  release_output_mutex (); | ||||||
|  | 	  master_fwd_thread->terminate_thread (); | ||||||
| 	} | 	} | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -1247,6 +1267,11 @@ fhandler_pty_master::close () | |||||||
|   if (!ForceCloseHandle (to_master)) |   if (!ForceCloseHandle (to_master)) | ||||||
|     termios_printf ("error closing to_master %p, %E", to_master); |     termios_printf ("error closing to_master %p, %E", to_master); | ||||||
|   from_master = to_master = NULL; |   from_master = to_master = NULL; | ||||||
|  |   if (!ForceCloseHandle (get_io_handle_cyg ())) | ||||||
|  |     termios_printf ("error closing io_handle_cyg %p, %E", get_io_handle_cyg ()); | ||||||
|  |   if (!ForceCloseHandle (to_master_cyg)) | ||||||
|  |     termios_printf ("error closing to_master_cyg %p, %E", to_master_cyg); | ||||||
|  |   get_io_handle_cyg () = to_master_cyg = NULL; | ||||||
|   ForceCloseHandle (echo_r); |   ForceCloseHandle (echo_r); | ||||||
|   ForceCloseHandle (echo_w); |   ForceCloseHandle (echo_w); | ||||||
|   echo_r = echo_w = NULL; |   echo_r = echo_w = NULL; | ||||||
| @@ -1353,7 +1378,7 @@ fhandler_pty_master::ioctl (unsigned int cmd, void *arg) | |||||||
|     case FIONREAD: |     case FIONREAD: | ||||||
|       { |       { | ||||||
| 	DWORD n; | 	DWORD n; | ||||||
| 	if (!::bytes_available (n, to_master)) | 	if (!::bytes_available (n, get_io_handle_cyg ())) | ||||||
| 	  { | 	  { | ||||||
| 	    set_errno (EINVAL); | 	    set_errno (EINVAL); | ||||||
| 	    return -1; | 	    return -1; | ||||||
| @@ -1523,6 +1548,13 @@ fhandler_pty_master::pty_master_thread () | |||||||
| 	      termios_printf ("DuplicateHandle (to_master), %E"); | 	      termios_printf ("DuplicateHandle (to_master), %E"); | ||||||
| 	      goto reply; | 	      goto reply; | ||||||
| 	    } | 	    } | ||||||
|  | 	  if (!DuplicateHandle (GetCurrentProcess (), to_master_cyg, | ||||||
|  | 				client, &repl.to_master_cyg, | ||||||
|  | 				0, TRUE, DUPLICATE_SAME_ACCESS)) | ||||||
|  | 	    { | ||||||
|  | 	      termios_printf ("DuplicateHandle (to_master_cyg), %E"); | ||||||
|  | 	      goto reply; | ||||||
|  | 	    } | ||||||
| 	} | 	} | ||||||
| reply: | reply: | ||||||
|       repl.error = GetLastError (); |       repl.error = GetLastError (); | ||||||
| @@ -1548,6 +1580,40 @@ pty_master_thread (VOID *arg) | |||||||
|   return ((fhandler_pty_master *) arg)->pty_master_thread (); |   return ((fhandler_pty_master *) arg)->pty_master_thread (); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | DWORD | ||||||
|  | fhandler_pty_master::pty_master_fwd_thread () | ||||||
|  | { | ||||||
|  |   DWORD rlen; | ||||||
|  |   char outbuf[OUT_BUFFER_SIZE]; | ||||||
|  |  | ||||||
|  |   termios_printf("Started."); | ||||||
|  |   for (;;) | ||||||
|  |     { | ||||||
|  |       if (!ReadFile (get_io_handle (), outbuf, sizeof outbuf, &rlen, NULL)) | ||||||
|  | 	{ | ||||||
|  | 	  termios_printf ("ReadFile for forwarding failed, %E"); | ||||||
|  | 	  break; | ||||||
|  | 	} | ||||||
|  |       ssize_t wlen = rlen; | ||||||
|  |       while (rlen>0) | ||||||
|  | 	{ | ||||||
|  | 	  if (!process_opost_output (to_master_cyg, outbuf, wlen, false)) | ||||||
|  | 	    { | ||||||
|  | 	      termios_printf ("WriteFile for forwarding failed, %E"); | ||||||
|  | 	      break; | ||||||
|  | 	    } | ||||||
|  | 	  rlen -= wlen; | ||||||
|  | 	} | ||||||
|  |     } | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static DWORD WINAPI | ||||||
|  | pty_master_fwd_thread (VOID *arg) | ||||||
|  | { | ||||||
|  |   return ((fhandler_pty_master *) arg)->pty_master_fwd_thread (); | ||||||
|  | } | ||||||
|  |  | ||||||
| bool | bool | ||||||
| fhandler_pty_master::setup () | fhandler_pty_master::setup () | ||||||
| { | { | ||||||
| @@ -1574,7 +1640,7 @@ fhandler_pty_master::setup () | |||||||
|     termios_printf ("can't set output_handle(%p) to non-blocking mode", |     termios_printf ("can't set output_handle(%p) to non-blocking mode", | ||||||
| 		    get_output_handle ()); | 		    get_output_handle ()); | ||||||
|  |  | ||||||
|   char pipename[sizeof("ptyNNNN-from-master")]; |   char pipename[sizeof("ptyNNNN-to-master-cyg")]; | ||||||
|   __small_sprintf (pipename, "pty%d-to-master", unit); |   __small_sprintf (pipename, "pty%d-to-master", unit); | ||||||
|   res = fhandler_pipe::create (&sec_none, &get_io_handle (), &to_master, |   res = fhandler_pipe::create (&sec_none, &get_io_handle (), &to_master, | ||||||
| 			       fhandler_pty_common::pipesize, pipename, 0); | 			       fhandler_pty_common::pipesize, pipename, 0); | ||||||
| @@ -1584,6 +1650,15 @@ fhandler_pty_master::setup () | |||||||
|       goto err; |       goto err; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |   __small_sprintf (pipename, "pty%d-to-master-cyg", unit); | ||||||
|  |   res = fhandler_pipe::create (&sec_none, &get_io_handle_cyg (), &to_master_cyg, | ||||||
|  | 			       fhandler_pty_common::pipesize, pipename, 0); | ||||||
|  |   if (res) | ||||||
|  |     { | ||||||
|  |       errstr = "output pipe for cygwin"; | ||||||
|  |       goto err; | ||||||
|  |     } | ||||||
|  |  | ||||||
|   ProtectHandle1 (get_io_handle (), from_pty); |   ProtectHandle1 (get_io_handle (), from_pty); | ||||||
|  |  | ||||||
|   __small_sprintf (pipename, "pty%d-echoloop", unit); |   __small_sprintf (pipename, "pty%d-echoloop", unit); | ||||||
| @@ -1643,28 +1718,38 @@ fhandler_pty_master::setup () | |||||||
|       errstr = "pty master control thread"; |       errstr = "pty master control thread"; | ||||||
|       goto err; |       goto err; | ||||||
|     } |     } | ||||||
|  |   master_fwd_thread = new cygthread (::pty_master_fwd_thread, this, "ptymf"); | ||||||
|  |   if (!master_fwd_thread) | ||||||
|  |     { | ||||||
|  |       errstr = "pty master forwarding thread"; | ||||||
|  |       goto err; | ||||||
|  |     } | ||||||
|  |  | ||||||
|   t.set_from_master (from_master); |   t.set_from_master (from_master); | ||||||
|   t.set_to_master (to_master); |   t.set_to_master (to_master); | ||||||
|  |   t.set_to_master_cyg (to_master_cyg); | ||||||
|   t.winsize.ws_col = 80; |   t.winsize.ws_col = 80; | ||||||
|   t.winsize.ws_row = 25; |   t.winsize.ws_row = 25; | ||||||
|   t.master_pid = myself->pid; |   t.master_pid = myself->pid; | ||||||
|  |  | ||||||
|   dev ().parse (DEV_PTYM_MAJOR, unit); |   dev ().parse (DEV_PTYM_MAJOR, unit); | ||||||
|  |  | ||||||
|   termios_printf ("this %p, pty%d opened - from_pty %p, to_pty %p", this, unit, |   termios_printf ("this %p, pty%d opened - from_pty <%p,%p>, to_pty %p", | ||||||
| 		  get_io_handle (), get_output_handle ()); | 	this, unit, get_io_handle (), get_io_handle_cyg (), | ||||||
|  | 	get_output_handle ()); | ||||||
|   return true; |   return true; | ||||||
|  |  | ||||||
| err: | err: | ||||||
|   __seterrno (); |   __seterrno (); | ||||||
|   close_maybe (get_io_handle ()); |   close_maybe (get_io_handle ()); | ||||||
|  |   close_maybe (get_io_handle_cyg ()); | ||||||
|   close_maybe (get_output_handle ()); |   close_maybe (get_output_handle ()); | ||||||
|   close_maybe (input_available_event); |   close_maybe (input_available_event); | ||||||
|   close_maybe (output_mutex); |   close_maybe (output_mutex); | ||||||
|   close_maybe (input_mutex); |   close_maybe (input_mutex); | ||||||
|   close_maybe (from_master); |   close_maybe (from_master); | ||||||
|   close_maybe (to_master); |   close_maybe (to_master); | ||||||
|  |   close_maybe (to_master_cyg); | ||||||
|   close_maybe (echo_r); |   close_maybe (echo_r); | ||||||
|   close_maybe (echo_w); |   close_maybe (echo_w); | ||||||
|   close_maybe (master_ctl); |   close_maybe (master_ctl); | ||||||
| @@ -1684,11 +1769,13 @@ fhandler_pty_master::fixup_after_fork (HANDLE parent) | |||||||
| 	{ | 	{ | ||||||
| 	  t.set_from_master (arch->from_master); | 	  t.set_from_master (arch->from_master); | ||||||
| 	  t.set_to_master (arch->to_master); | 	  t.set_to_master (arch->to_master); | ||||||
|  | 	  t.set_to_master_cyg (arch->to_master_cyg); | ||||||
| 	} | 	} | ||||||
|       arch->dwProcessId = wpid; |       arch->dwProcessId = wpid; | ||||||
|     } |     } | ||||||
|   from_master = arch->from_master; |   from_master = arch->from_master; | ||||||
|   to_master = arch->to_master; |   to_master = arch->to_master; | ||||||
|  |   to_master_cyg = arch->to_master_cyg; | ||||||
|   report_tty_counts (this, "inherited master", ""); |   report_tty_counts (this, "inherited master", ""); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1698,7 +1785,7 @@ fhandler_pty_master::fixup_after_exec () | |||||||
|   if (!close_on_exec ()) |   if (!close_on_exec ()) | ||||||
|     fixup_after_fork (spawn_info->parent); |     fixup_after_fork (spawn_info->parent); | ||||||
|   else |   else | ||||||
|     from_master = to_master = NULL; |     from_master = to_master = to_master_cyg = NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
| BOOL | BOOL | ||||||
|   | |||||||
| @@ -80,7 +80,7 @@ details. */ | |||||||
| #define copyfd_set(to, from, n) memcpy (to, from, sizeof_fd_set (n)); | #define copyfd_set(to, from, n) memcpy (to, from, sizeof_fd_set (n)); | ||||||
|  |  | ||||||
| #define set_handle_or_return_if_not_open(h, s) \ | #define set_handle_or_return_if_not_open(h, s) \ | ||||||
|   h = (s)->fh->get_handle (); \ |   h = (s)->fh->get_io_handle_cyg (); \ | ||||||
|   if (cygheap->fdtab.not_open ((s)->fd)) \ |   if (cygheap->fdtab.not_open ((s)->fd)) \ | ||||||
|     { \ |     { \ | ||||||
|       (s)->thread_errno =  EBADF; \ |       (s)->thread_errno =  EBADF; \ | ||||||
| @@ -1264,7 +1264,7 @@ fhandler_base::select_read (select_stuff *ss) | |||||||
|       s->startup = no_startup; |       s->startup = no_startup; | ||||||
|       s->verify = verify_ok; |       s->verify = verify_ok; | ||||||
|     } |     } | ||||||
|   s->h = get_handle (); |   s->h = get_io_handle_cyg (); | ||||||
|   s->read_selected = true; |   s->read_selected = true; | ||||||
|   s->read_ready = true; |   s->read_ready = true; | ||||||
|   return s; |   return s; | ||||||
|   | |||||||
| @@ -92,12 +92,15 @@ public: | |||||||
| private: | private: | ||||||
|   HANDLE _from_master; |   HANDLE _from_master; | ||||||
|   HANDLE _to_master; |   HANDLE _to_master; | ||||||
|  |   HANDLE _to_master_cyg; | ||||||
|  |  | ||||||
| public: | public: | ||||||
|   HANDLE from_master() const { return _from_master; } |   HANDLE from_master() const { return _from_master; } | ||||||
|   HANDLE to_master() const { return _to_master; } |   HANDLE to_master() const { return _to_master; } | ||||||
|  |   HANDLE to_master_cyg() const { return _to_master_cyg; } | ||||||
|   void set_from_master (HANDLE h) { _from_master = h; } |   void set_from_master (HANDLE h) { _from_master = h; } | ||||||
|   void set_to_master (HANDLE h) { _to_master = h; } |   void set_to_master (HANDLE h) { _to_master = h; } | ||||||
|  |   void set_to_master_cyg (HANDLE h) { _to_master_cyg = h; } | ||||||
|  |  | ||||||
|   int read_retval; |   int read_retval; | ||||||
|   bool was_opened;	/* True if opened at least once. */ |   bool was_opened;	/* True if opened at least once. */ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user