Skip to content

Commit 98ca669

Browse files
committed
Do not exit fabric-sync-app before apps are terminated
1 parent 70fa557 commit 98ca669

File tree

1 file changed

+29
-26
lines changed

1 file changed

+29
-26
lines changed

examples/fabric-admin/scripts/fabric-sync-app.py

+29-26
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,7 @@ async def forward_f(prefix: bytes, f_in: asyncio.StreamReader,
3131
3232
This function can optionally feed received lines to a callback function.
3333
"""
34-
while True:
35-
line = await f_in.readline()
36-
if not line:
37-
break
34+
while line := await f_in.readline():
3835
if cb is not None:
3936
cb(line)
4037
f_out.buffer.write(prefix)
@@ -68,11 +65,7 @@ async def forward_stdin(f_out: asyncio.StreamWriter):
6865
reader = asyncio.StreamReader()
6966
protocol = asyncio.StreamReaderProtocol(reader)
7067
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():
7669
f_out.write(line)
7770
await f_out.drain()
7871

@@ -206,12 +199,16 @@ async def main(args):
206199
passcode=args.passcode,
207200
))
208201

202+
loop = asyncio.get_event_loop()
203+
209204
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)
213211

214-
loop = asyncio.get_event_loop()
215212
loop.add_signal_handler(signal.SIGINT, terminate)
216213
loop.add_signal_handler(signal.SIGTERM, terminate)
217214

@@ -238,7 +235,8 @@ def terminate():
238235
cmd,
239236
# Wait for the log message indicating that the bridge has been
240237
# 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)
242240

243241
# Open commissioning window with original setup code for the bridge.
244242
cw_endpoint_id = 0
@@ -250,18 +248,23 @@ def terminate():
250248
f" {cw_option} {cw_timeout} {cw_iteration} {cw_discriminator}")
251249

252250
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()
265268

266269

267270
if __name__ == "__main__":

0 commit comments

Comments
 (0)