Better error type for inactive thread pools (#1787)

* Better error type for inactive thread pools

* Soundness

* Typos

* PR comments

* Defer ELG shutdown

* Remove redundant try
This commit is contained in:
David Evans 2021-03-22 10:01:39 +00:00 committed by GitHub
parent 1376c7d2d3
commit 97919c94f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 30 additions and 2 deletions

View File

@ -15,6 +15,13 @@
import Dispatch
import NIOConcurrencyHelpers
/// Errors that may be thrown when executing work on a `NIOThreadPool`
public enum NIOThreadPoolError {
/// The `NIOThreadPool` was not active.
public struct ThreadPoolInactive: Error { }
}
/// A thread pool that should be used if some (kernel thread) blocking work
/// needs to be performed for which no non-blocking API exists.
@ -206,6 +213,7 @@ public final class NIOThreadPool {
}
extension NIOThreadPool {
/// Runs the submitted closure if the thread pool is still active, otherwise fails the promise.
/// The closure will be run on the thread pool so can do blocking work.
///
@ -217,7 +225,7 @@ extension NIOThreadPool {
let promise = eventLoop.makePromise(of: T.self)
self.submit { shouldRun in
guard case shouldRun = NIOThreadPool.WorkItemState.active else {
promise.fail(ChannelError.ioOnClosedChannel)
promise.fail(NIOThreadPoolError.ThreadPoolInactive())
return
}
do {

View File

@ -71,6 +71,7 @@ extension NonBlockingFileIOTest {
("testReadFromEOFDeliversExactlyOneChunk", testReadFromEOFDeliversExactlyOneChunk),
("testReadChunkedFromOffsetFileRegion", testReadChunkedFromOffsetFileRegion),
("testReadManyChunks", testReadManyChunks),
("testThrowsErrorOnUnstartedPool", testThrowsErrorOnUnstartedPool),
]
}
}

View File

@ -138,7 +138,7 @@ class NonBlockingFileIOTest: XCTestCase {
byteCount: 1,
allocator: self.allocator,
eventLoop: self.eventLoop).wait()) { error in
XCTAssertEqual(.ioOnClosedChannel, error as? ChannelError)
XCTAssertTrue(error is NIOThreadPoolError.ThreadPoolInactive)
}
return [readFH, writeFH]
}
@ -915,4 +915,23 @@ class NonBlockingFileIOTest: XCTestCase {
XCTAssertEqual(numberOfChunks, numberOfCalls.load())
})
}
func testThrowsErrorOnUnstartedPool() throws {
withTemporaryFile(content: "hello, world") { fileHandle, path in
let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
defer {
XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully())
}
let expectation = XCTestExpectation(description: "Opened file")
let threadPool = NIOThreadPool(numberOfThreads: 1)
let fileIO = NonBlockingFileIO(threadPool: threadPool)
fileIO.openFile(path: path, eventLoop: eventLoopGroup.next()).whenFailure { (error) in
XCTAssertTrue(error is NIOThreadPoolError.ThreadPoolInactive)
expectation.fulfill()
}
self.wait(for: [expectation], timeout: 1.0)
}
}
}