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:
parent
1376c7d2d3
commit
97919c94f9
|
@ -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 {
|
||||
|
|
|
@ -71,6 +71,7 @@ extension NonBlockingFileIOTest {
|
|||
("testReadFromEOFDeliversExactlyOneChunk", testReadFromEOFDeliversExactlyOneChunk),
|
||||
("testReadChunkedFromOffsetFileRegion", testReadChunkedFromOffsetFileRegion),
|
||||
("testReadManyChunks", testReadManyChunks),
|
||||
("testThrowsErrorOnUnstartedPool", testThrowsErrorOnUnstartedPool),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue