@@ -12,10 +12,15 @@ use super::util::{get_existing_namespaces, get_target_subnet};
12
12
use super :: vpn:: { verify_auth, Protocol } ;
13
13
use anyhow:: { anyhow, bail} ;
14
14
use log:: { debug, error, info, warn} ;
15
+ use signal_hook:: { iterator:: Signals , SIGINT } ;
15
16
use std:: io:: { self , Write } ;
16
17
use std:: net:: { IpAddr , Ipv4Addr } ;
17
18
18
19
pub fn exec ( command : ExecCommand ) -> anyhow:: Result < ( ) > {
20
+ // this captures all sigint signals
21
+ // ignore for now, they are automatically passed on to the child
22
+ let signals = Signals :: new ( & [ SIGINT ] ) ?;
23
+
19
24
let provider: VpnProvider ;
20
25
let server_name: String ;
21
26
let protocol: Protocol ;
@@ -276,37 +281,50 @@ pub fn exec(command: ExecCommand) -> anyhow::Result<()> {
276
281
"Process {} still running, assumed to be daemon - will leave network namespace alive until ctrl+C received" ,
277
282
pid
278
283
) ;
279
- stay_alive ( pid) ?;
284
+ stay_alive ( Some ( pid) , signals ) ?;
280
285
} else if command. keep_alive {
281
286
info ! ( "Keep-alive flag active - will leave network namespace alive until ctrl+C received" ) ;
282
- stay_alive ( pid ) ?;
287
+ stay_alive ( None , signals ) ?;
283
288
}
284
289
285
290
Ok ( ( ) )
286
291
}
287
292
288
293
// Block waiting for SIGINT
289
- fn stay_alive ( pid : u32 ) -> anyhow:: Result < ( ) > {
290
- let recv = ctrl_channel ( pid) ;
291
- recv?. recv ( ) . unwrap ( ) ;
292
- Ok ( ( ) )
293
- }
294
-
295
- // Handle waiting for SIGINT
296
- fn ctrl_channel ( pid : u32 ) -> Result < std:: sync:: mpsc:: Receiver < ( ) > , ctrlc:: Error > {
294
+ fn stay_alive ( pid : Option < u32 > , mut signals : Signals ) -> anyhow:: Result < ( ) > {
297
295
let ( sender, receiver) = std:: sync:: mpsc:: channel ( ) ;
298
- ctrlc:: set_handler ( move || {
299
- let _ = sender. send ( ( ) ) ;
300
- info ! (
301
- "SIGINT received, killing process {} and terminating..." ,
302
- pid
303
- ) ;
304
- nix:: sys:: signal:: kill (
305
- nix:: unistd:: Pid :: from_raw ( pid as i32 ) ,
306
- nix:: sys:: signal:: Signal :: SIGKILL ,
307
- )
308
- . ok ( ) ;
309
- } ) ?;
310
296
311
- Ok ( receiver)
297
+ // discard old signals
298
+ for _old in signals. pending ( ) {
299
+ // pass, just empty the iterator
300
+ }
301
+
302
+ let handle = signals. handle ( ) ;
303
+
304
+ let thread = std:: thread:: spawn ( move || {
305
+ for _sig in signals. forever ( ) {
306
+ if let Some ( pid) = pid {
307
+ info ! (
308
+ "SIGINT received, killing process {} and terminating..." ,
309
+ pid
310
+ ) ;
311
+ nix:: sys:: signal:: kill (
312
+ nix:: unistd:: Pid :: from_raw ( pid as i32 ) ,
313
+ nix:: sys:: signal:: Signal :: SIGKILL ,
314
+ )
315
+ . ok ( ) ;
316
+ } else {
317
+ info ! ( "SIGINT received, terminating..." , ) ;
318
+ }
319
+ let _ = sender. send ( ( ) ) ;
320
+ }
321
+ } ) ;
322
+
323
+ // this blocks until sender sends, so until sigint is received
324
+ receiver. recv ( ) . unwrap ( ) ;
325
+
326
+ handle. close ( ) ;
327
+ thread. join ( ) . unwrap ( ) ;
328
+
329
+ Ok ( ( ) )
312
330
}
0 commit comments