@@ -5,7 +5,6 @@ use alacritty_terminal::tty::{ChildEvent, EventedPty, EventedReadWrite};
55use anyhow:: Context ;
66use polling:: { Event , PollMode , Poller } ;
77use std:: collections:: HashMap ;
8- use std:: net:: { TcpListener , TcpStream } ;
98use std:: sync:: Arc ;
109use tracing:: { error, trace} ;
1110use wezterm_ssh:: {
@@ -14,10 +13,23 @@ use wezterm_ssh::{
1413} ;
1514
1615#[ cfg( unix) ]
17- use std:: os:: fd:: { AsFd , AsRawFd } ;
16+ use signal_hook:: {
17+ consts,
18+ low_level:: { pipe, unregister} ,
19+ SigId ,
20+ } ;
21+
22+ #[ cfg( unix) ]
23+ use std:: os:: {
24+ fd:: { AsFd , AsRawFd } ,
25+ unix:: net:: UnixStream ,
26+ } ;
1827
1928#[ cfg( windows) ]
20- use std:: os:: windows:: io:: { AsRawSocket , AsSocket } ;
29+ use std:: {
30+ net:: { TcpListener , TcpStream } ,
31+ os:: windows:: io:: { AsRawSocket , AsSocket } ,
32+ } ;
2133
2234// Interest in PTY read/writes.
2335#[ cfg( unix) ]
@@ -30,12 +42,22 @@ const PTY_CHILD_EVENT_TOKEN: usize = 1;
3042pub struct Pty {
3143 pub pty : SshPty ,
3244 pub child : SshChildProcess ,
33- pub signal : TcpStream ,
45+ #[ cfg( unix) ]
46+ pub signals : UnixStream ,
47+ #[ cfg( unix) ]
48+ pub sig_id : SigId ,
49+ #[ cfg( windows) ]
50+ pub signals : TcpStream ,
3451}
3552
3653impl Drop for Pty {
3754 fn drop ( & mut self ) {
3855 let _ = self . child . kill ( ) ;
56+
57+ // Clear signal-hook handler.
58+ #[ cfg( unix) ]
59+ unregister ( self . sig_id ) ;
60+
3961 let _ = self . child . wait ( ) ;
4062 }
4163}
@@ -66,16 +88,16 @@ impl EventedReadWrite for Pty {
6688 interest. key = PTY_READ_WRITE_TOKEN ;
6789 let _ = self . pty . reader . set_non_blocking ( true ) ;
6890 let _ = self . pty . writer . set_non_blocking ( true ) ;
69- let _ = self . signal . set_nonblocking ( true ) ;
91+ let _ = self . signals . set_nonblocking ( true ) ;
7092
7193 #[ cfg( unix) ]
7294 {
7395 poller. add_with_mode ( self . pty . reader . as_raw_fd ( ) , interest, mode) ?;
7496 poller. add_with_mode ( self . pty . writer . as_raw_fd ( ) , interest, mode) ?;
7597
7698 poller. add_with_mode (
77- self . signal . as_raw_fd ( ) ,
78- Event :: readable ( PTY_CHILD_EVENT_TOKEN ) ,
99+ & self . signals ,
100+ Event :: writable ( PTY_CHILD_EVENT_TOKEN ) ,
79101 PollMode :: Level ,
80102 ) ?;
81103 }
@@ -86,8 +108,8 @@ impl EventedReadWrite for Pty {
86108 poller. add_with_mode ( self . pty . writer . as_raw_socket ( ) , interest, mode) ?;
87109
88110 poller. add_with_mode (
89- self . signal . as_raw_socket ( ) ,
90- Event :: readable ( crate :: ssh :: PTY_CHILD_EVENT_TOKEN ) ,
111+ self . signals . as_raw_socket ( ) ,
112+ Event :: readable ( PTY_CHILD_EVENT_TOKEN ) ,
91113 PollMode :: Level ,
92114 ) ?;
93115 }
@@ -109,8 +131,8 @@ impl EventedReadWrite for Pty {
109131 poller. modify_with_mode ( self . pty . writer . as_fd ( ) , interest, mode) ?;
110132
111133 poller. modify_with_mode (
112- self . signal . as_fd ( ) ,
113- Event :: readable ( PTY_CHILD_EVENT_TOKEN ) ,
134+ & self . signals ,
135+ Event :: writable ( PTY_CHILD_EVENT_TOKEN ) ,
114136 PollMode :: Level ,
115137 ) ?;
116138 }
@@ -121,8 +143,8 @@ impl EventedReadWrite for Pty {
121143 poller. modify_with_mode ( self . pty . writer . as_socket ( ) , interest, mode) ?;
122144
123145 poller. modify_with_mode (
124- self . signal . as_socket ( ) ,
125- Event :: readable ( crate :: ssh :: PTY_CHILD_EVENT_TOKEN ) ,
146+ self . signals . as_socket ( ) ,
147+ Event :: readable ( PTY_CHILD_EVENT_TOKEN ) ,
126148 PollMode :: Level ,
127149 ) ?;
128150 }
@@ -136,15 +158,15 @@ impl EventedReadWrite for Pty {
136158 poller. delete ( self . pty . reader . as_fd ( ) ) ?;
137159 poller. delete ( self . pty . writer . as_fd ( ) ) ?;
138160
139- poller. delete ( self . signal . as_fd ( ) ) ?;
161+ poller. delete ( & self . signals ) ?;
140162 }
141163
142164 #[ cfg( windows) ]
143165 {
144166 poller. delete ( self . pty . reader . as_socket ( ) ) ?;
145167 poller. delete ( self . pty . writer . as_socket ( ) ) ?;
146168
147- poller. delete ( self . signal . as_socket ( ) ) ?;
169+ poller. delete ( self . signals . as_socket ( ) ) ?;
148170 }
149171
150172 Ok ( ( ) )
@@ -206,10 +228,6 @@ impl Pty {
206228 verify. answer ( true ) . await . context ( "send verify response" ) ?;
207229 }
208230 SessionEvent :: Authenticate ( auth) => {
209- for a in auth. prompts . iter ( ) {
210- println ! ( "prompt: {}" , a. prompt) ;
211- }
212-
213231 let mut answers = vec ! [ ] ;
214232 for prompt in auth. prompts . iter ( ) {
215233 if prompt. prompt . contains ( "Password" ) {
@@ -234,15 +252,43 @@ impl Pty {
234252
235253 // FIXME: set in settings
236254 let mut env = HashMap :: new ( ) ;
237- env. insert ( "LANG" . to_string ( ) , "zh_CN.utf8 " . to_string ( ) ) ;
255+ env. insert ( "LANG" . to_string ( ) , "en_US.UTF-8 " . to_string ( ) ) ;
238256 env. insert ( "LC_COLLATE" . to_string ( ) , "C" . to_string ( ) ) ;
239257
240258 let ( pty, child) = session
241259 . request_pty ( "xterm-256color" , PtySize :: default ( ) , None , Some ( env) )
242260 . await ?;
243261
244- let signal = tcp_signal ( ) ?;
245- Ok ( Pty { pty, child, signal } )
262+ #[ cfg( unix) ]
263+ {
264+ // Prepare signal handling before spawning child.
265+ let ( signals, sig_id) = {
266+ let ( sender, recv) = UnixStream :: pair ( ) ?;
267+
268+ // Register the recv end of the pipe for SIGCHLD.
269+ let sig_id = pipe:: register ( consts:: SIGCHLD , sender) ?;
270+ recv. set_nonblocking ( true ) ?;
271+ ( recv, sig_id)
272+ } ;
273+
274+ Ok ( Pty {
275+ pty,
276+ child,
277+ signals,
278+ sig_id,
279+ } )
280+ }
281+
282+ #[ cfg( windows) ]
283+ {
284+ let listener = TcpListener :: bind ( "127.0.0.1:0" ) ?;
285+ let signals = TcpStream :: connect ( listener. local_addr ( ) ?) ?;
286+ Ok ( Pty {
287+ pty,
288+ child,
289+ signals,
290+ } )
291+ }
246292 } )
247293 }
248294}
@@ -261,8 +307,3 @@ pub enum Authentication {
261307 Password ( String , String ) ,
262308 Config ,
263309}
264-
265- fn tcp_signal ( ) -> std:: io:: Result < TcpStream > {
266- let listener = TcpListener :: bind ( "127.0.0.1:0" ) ?;
267- TcpStream :: connect ( listener. local_addr ( ) ?)
268- }
0 commit comments