@@ -5,7 +5,6 @@ use alacritty_terminal::tty::{ChildEvent, EventedPty, EventedReadWrite};
5
5
use anyhow:: Context ;
6
6
use polling:: { Event , PollMode , Poller } ;
7
7
use std:: collections:: HashMap ;
8
- use std:: net:: { TcpListener , TcpStream } ;
9
8
use std:: sync:: Arc ;
10
9
use tracing:: { error, trace} ;
11
10
use wezterm_ssh:: {
@@ -14,10 +13,23 @@ use wezterm_ssh::{
14
13
} ;
15
14
16
15
#[ 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
+ } ;
18
27
19
28
#[ cfg( windows) ]
20
- use std:: os:: windows:: io:: { AsRawSocket , AsSocket } ;
29
+ use std:: {
30
+ net:: { TcpListener , TcpStream } ,
31
+ os:: windows:: io:: { AsRawSocket , AsSocket } ,
32
+ } ;
21
33
22
34
// Interest in PTY read/writes.
23
35
#[ cfg( unix) ]
@@ -30,12 +42,22 @@ const PTY_CHILD_EVENT_TOKEN: usize = 1;
30
42
pub struct Pty {
31
43
pub pty : SshPty ,
32
44
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 ,
34
51
}
35
52
36
53
impl Drop for Pty {
37
54
fn drop ( & mut self ) {
38
55
let _ = self . child . kill ( ) ;
56
+
57
+ // Clear signal-hook handler.
58
+ #[ cfg( unix) ]
59
+ unregister ( self . sig_id ) ;
60
+
39
61
let _ = self . child . wait ( ) ;
40
62
}
41
63
}
@@ -66,16 +88,16 @@ impl EventedReadWrite for Pty {
66
88
interest. key = PTY_READ_WRITE_TOKEN ;
67
89
let _ = self . pty . reader . set_non_blocking ( true ) ;
68
90
let _ = self . pty . writer . set_non_blocking ( true ) ;
69
- let _ = self . signal . set_nonblocking ( true ) ;
91
+ let _ = self . signals . set_nonblocking ( true ) ;
70
92
71
93
#[ cfg( unix) ]
72
94
{
73
95
poller. add_with_mode ( self . pty . reader . as_raw_fd ( ) , interest, mode) ?;
74
96
poller. add_with_mode ( self . pty . writer . as_raw_fd ( ) , interest, mode) ?;
75
97
76
98
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 ) ,
79
101
PollMode :: Level ,
80
102
) ?;
81
103
}
@@ -86,8 +108,8 @@ impl EventedReadWrite for Pty {
86
108
poller. add_with_mode ( self . pty . writer . as_raw_socket ( ) , interest, mode) ?;
87
109
88
110
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 ) ,
91
113
PollMode :: Level ,
92
114
) ?;
93
115
}
@@ -109,8 +131,8 @@ impl EventedReadWrite for Pty {
109
131
poller. modify_with_mode ( self . pty . writer . as_fd ( ) , interest, mode) ?;
110
132
111
133
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 ) ,
114
136
PollMode :: Level ,
115
137
) ?;
116
138
}
@@ -121,8 +143,8 @@ impl EventedReadWrite for Pty {
121
143
poller. modify_with_mode ( self . pty . writer . as_socket ( ) , interest, mode) ?;
122
144
123
145
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 ) ,
126
148
PollMode :: Level ,
127
149
) ?;
128
150
}
@@ -136,15 +158,15 @@ impl EventedReadWrite for Pty {
136
158
poller. delete ( self . pty . reader . as_fd ( ) ) ?;
137
159
poller. delete ( self . pty . writer . as_fd ( ) ) ?;
138
160
139
- poller. delete ( self . signal . as_fd ( ) ) ?;
161
+ poller. delete ( & self . signals ) ?;
140
162
}
141
163
142
164
#[ cfg( windows) ]
143
165
{
144
166
poller. delete ( self . pty . reader . as_socket ( ) ) ?;
145
167
poller. delete ( self . pty . writer . as_socket ( ) ) ?;
146
168
147
- poller. delete ( self . signal . as_socket ( ) ) ?;
169
+ poller. delete ( self . signals . as_socket ( ) ) ?;
148
170
}
149
171
150
172
Ok ( ( ) )
@@ -206,10 +228,6 @@ impl Pty {
206
228
verify. answer ( true ) . await . context ( "send verify response" ) ?;
207
229
}
208
230
SessionEvent :: Authenticate ( auth) => {
209
- for a in auth. prompts . iter ( ) {
210
- println ! ( "prompt: {}" , a. prompt) ;
211
- }
212
-
213
231
let mut answers = vec ! [ ] ;
214
232
for prompt in auth. prompts . iter ( ) {
215
233
if prompt. prompt . contains ( "Password" ) {
@@ -234,15 +252,43 @@ impl Pty {
234
252
235
253
// FIXME: set in settings
236
254
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 ( ) ) ;
238
256
env. insert ( "LC_COLLATE" . to_string ( ) , "C" . to_string ( ) ) ;
239
257
240
258
let ( pty, child) = session
241
259
. request_pty ( "xterm-256color" , PtySize :: default ( ) , None , Some ( env) )
242
260
. await ?;
243
261
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
+ }
246
292
} )
247
293
}
248
294
}
@@ -261,8 +307,3 @@ pub enum Authentication {
261
307
Password ( String , String ) ,
262
308
Config ,
263
309
}
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