Skip to content

Commit c0efd9c

Browse files
committed
Make sure we return after gracefully shutdown
# Motivation After calling `shutdownGracefully` in our `ServiceGroup` we know that one of two things happened: 1. We got an error so something went wrong 2. We got no error so all services finished In the 2. case, there might still be a few child tasks in the task group e.g. the graceful shutdown timeout task. We are currently still iterating the remaining child task results which might lead into unexpected fatal errors. # Modification This PR makes sure that after we have successfully shutdown we are stopping iterating the child task results. # Result No more unexpected fatal errors.
1 parent 026ed0d commit c0efd9c

File tree

2 files changed

+30
-0
lines changed

2 files changed

+30
-0
lines changed

Sources/ServiceLifecycle/ServiceGroup.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ public actor ServiceGroup: Sendable {
332332
group: &group,
333333
gracefulShutdownManagers: gracefulShutdownManagers
334334
)
335+
return .success(())
335336
} catch {
336337
return .failure(error)
337338
}
@@ -425,6 +426,7 @@ public actor ServiceGroup: Sendable {
425426
group: &group,
426427
gracefulShutdownManagers: gracefulShutdownManagers
427428
)
429+
return .success(())
428430
} catch {
429431
return .failure(error)
430432
}
@@ -451,6 +453,7 @@ public actor ServiceGroup: Sendable {
451453
group: &group,
452454
gracefulShutdownManagers: gracefulShutdownManagers
453455
)
456+
return .success(())
454457
} catch {
455458
return .failure(error)
456459
}

Tests/ServiceLifecycleTests/ServiceGroupTests.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,6 +1112,33 @@ final class ServiceGroupTests: XCTestCase {
11121112
}
11131113
}
11141114

1115+
func testGracefulShutdownWithMaximumDuration() async throws {
1116+
let mockService = MockService(description: "Service1")
1117+
let serviceGroup = self.makeServiceGroup(
1118+
services: [.init(service: mockService)],
1119+
gracefulShutdownSignals: [.sigalrm],
1120+
maximumGracefulShutdownDuration: .seconds(0.1)
1121+
)
1122+
1123+
try await withThrowingTaskGroup(of: Void.self) { group in
1124+
group.addTask {
1125+
try await serviceGroup.run()
1126+
}
1127+
1128+
var eventIterator = mockService.events.makeAsyncIterator()
1129+
await XCTAsyncAssertEqual(await eventIterator.next(), .run)
1130+
1131+
await serviceGroup.triggerGracefulShutdown()
1132+
1133+
await XCTAsyncAssertEqual(await eventIterator.next(), .shutdownGracefully)
1134+
1135+
1136+
await mockService.resumeRunContinuation(with: .success(()))
1137+
1138+
try await XCTAsyncAssertNoThrow(await group.next())
1139+
}
1140+
}
1141+
11151142
func testGracefulShutdownEscalation_whenNoCancellationEscalation() async throws {
11161143
let mockService = MockService(description: "Service1")
11171144
let serviceGroup = self.makeServiceGroup(

0 commit comments

Comments
 (0)