Skip to content

Commit 0e0a561

Browse files
authored
fix: Exit with code 2 when adapters disconnects (#28013)
1 parent 21fa5cb commit 0e0a561

File tree

2 files changed

+9
-9
lines changed

2 files changed

+9
-9
lines changed

lib/controller.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -281,17 +281,16 @@ export class Controller {
281281
}
282282
}
283283

284-
async stop(restart = false): Promise<void> {
284+
async stop(restart = false, code = 0): Promise<void> {
285285
this.sdNotify?.notifyStopping();
286286

287-
let code = 0;
288-
287+
let localCode = 0;
289288
for (const extension of this.extensions) {
290289
try {
291290
await extension.stop();
292291
} catch (error) {
293292
logger.error(`Failed to stop '${extension.constructor.name}' (${(error as Error).stack})`);
294-
code = 1;
293+
localCode = 1;
295294
}
296295
}
297296

@@ -306,11 +305,11 @@ export class Controller {
306305
logger.info("Stopped Zigbee2MQTT");
307306
} catch (error) {
308307
logger.error(`Failed to stop Zigbee2MQTT (${(error as Error).stack})`);
309-
code = 1;
308+
localCode = 1;
310309
}
311310

312311
this.sdNotify?.stop();
313-
return await this.exit(code, restart);
312+
return await this.exit(code !== 0 ? code : localCode, restart);
314313
}
315314

316315
async exit(code: number, restart = false): Promise<void> {
@@ -320,7 +319,7 @@ export class Controller {
320319

321320
@bind async onZigbeeAdapterDisconnected(): Promise<void> {
322321
logger.error("Adapter disconnected, stopping");
323-
await this.stop();
322+
await this.stop(false, 2);
324323
}
325324

326325
@bind async publishEntityState(entity: Group | Device, payload: KeyValue, stateChangeReason?: StateChangeReason): Promise<void> {

test/controller.test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -412,14 +412,15 @@ describe("Controller", () => {
412412
});
413413

414414
it("Start controller adapter disconnects", async () => {
415-
mockZHController.stop.mockRejectedValueOnce("failed");
415+
// Fail to stop extension exit code 1 should not override adapter disconnect exit code 2
416+
vi.spyOn(Array.from(controller.extensions)[0], "stop").mockRejectedValueOnce(new Error("failed"));
416417
await controller.start();
417418
await mockZHEvents.adapterDisconnected();
418419
await flushPromises();
419420
expect(mockMQTTEndAsync).toHaveBeenCalledTimes(1);
420421
expect(mockZHController.stop).toHaveBeenCalledTimes(1);
421422
expect(mockExit).toHaveBeenCalledTimes(1);
422-
expect(mockExit).toHaveBeenCalledWith(1, false);
423+
expect(mockExit).toHaveBeenCalledWith(2, false);
423424
});
424425

425426
it("does not throw when extension fails to stop on controller stop", async () => {

0 commit comments

Comments
 (0)