@@ -31,10 +31,7 @@ async def forward_f(prefix: bytes, f_in: asyncio.StreamReader,
31
31
32
32
This function can optionally feed received lines to a callback function.
33
33
"""
34
- while True :
35
- line = await f_in .readline ()
36
- if not line :
37
- break
34
+ while line := await f_in .readline ():
38
35
if cb is not None :
39
36
cb (line )
40
37
f_out .buffer .write (prefix )
@@ -68,11 +65,7 @@ async def forward_stdin(f_out: asyncio.StreamWriter):
68
65
reader = asyncio .StreamReader ()
69
66
protocol = asyncio .StreamReaderProtocol (reader )
70
67
await loop .connect_read_pipe (lambda : protocol , sys .stdin )
71
- while True :
72
- line = await reader .readline ()
73
- if not line :
74
- # Exit on Ctrl-D (EOF).
75
- sys .exit (0 )
68
+ while line := await reader .readline ():
76
69
f_out .write (line )
77
70
await f_out .drain ()
78
71
@@ -206,12 +199,16 @@ async def main(args):
206
199
passcode = args .passcode ,
207
200
))
208
201
202
+ loop = asyncio .get_event_loop ()
203
+
209
204
def terminate ():
210
- admin .terminate ()
211
- bridge .terminate ()
212
- sys .exit (0 )
205
+ with contextlib .suppress (ProcessLookupError ):
206
+ admin .terminate ()
207
+ with contextlib .suppress (ProcessLookupError ):
208
+ bridge .terminate ()
209
+ loop .remove_signal_handler (signal .SIGINT )
210
+ loop .remove_signal_handler (signal .SIGTERM )
213
211
214
- loop = asyncio .get_event_loop ()
215
212
loop .add_signal_handler (signal .SIGINT , terminate )
216
213
loop .add_signal_handler (signal .SIGTERM , terminate )
217
214
@@ -238,7 +235,8 @@ def terminate():
238
235
cmd ,
239
236
# Wait for the log message indicating that the bridge has been
240
237
# added to the fabric.
241
- f"Commissioning complete for node ID { bridge_node_id :#018x} : success" )
238
+ f"Commissioning complete for node ID { bridge_node_id :#018x} : success" ,
239
+ timeout = 30 )
242
240
243
241
# Open commissioning window with original setup code for the bridge.
244
242
cw_endpoint_id = 0
@@ -250,18 +248,23 @@ def terminate():
250
248
f" { cw_option } { cw_timeout } { cw_iteration } { cw_discriminator } " )
251
249
252
250
try :
253
- await asyncio .gather (
254
- forward_pipe (pipe , admin .p .stdin ) if pipe else forward_stdin (admin .p .stdin ),
255
- admin .wait (),
256
- bridge .wait (),
257
- )
258
- except SystemExit :
259
- admin .terminate ()
260
- bridge .terminate ()
261
- except Exception :
262
- admin .terminate ()
263
- bridge .terminate ()
264
- raise
251
+ forward = forward_pipe (pipe , admin .p .stdin ) if pipe else forward_stdin (admin .p .stdin )
252
+ # Wait for any of the tasks to complete.
253
+ _ , pending = await asyncio .wait ([
254
+ asyncio .create_task (admin .wait ()),
255
+ asyncio .create_task (bridge .wait ()),
256
+ asyncio .create_task (forward ),
257
+ ], return_when = asyncio .FIRST_COMPLETED )
258
+ # Cancel the remaining tasks.
259
+ for task in pending :
260
+ task .cancel ()
261
+ except Exception as e :
262
+ print (e , file = sys .stderr )
263
+
264
+ terminate ()
265
+ # Make sure that we will not return until both processes are terminated.
266
+ await admin .wait ()
267
+ await bridge .wait ()
265
268
266
269
267
270
if __name__ == "__main__" :
0 commit comments