Remove not on eventLoop precondition for NIOPipeBootstrap (#1977)
Motivation: Currently you cannot create a NIOPipeBootstrap when you are on an event loop due to a precondition check. This check seeks to prevent consumers of the API from passing in a file descriptor thats referencing a file on disk or on the network. The method at hand 'validateFileDescriptorIsNotAFile' uses fstat, which potentially could block the event loop especially if the fd is referencing a file over the network. This check however prevents certain use cases of SwiftNIO, where the downsides of a consumer of this api blocking their own event loop do not weigh in against preventing an entire use case from SwiftNIO. Modifications: Removed the precondition Result: After this change it will be possible to feed file descriptors into the bootstrap which potentially block the current event loop. A potential (portable) replacement for fstat still has to be found in order to solve this problem completely.
This commit is contained in:
parent
d906b890d5
commit
787e2287d0
|
@ -1023,8 +1023,6 @@ public final class NIOPipeBootstrap {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func validateFileDescriptorIsNotAFile(_ descriptor: CInt) throws {
|
private func validateFileDescriptorIsNotAFile(_ descriptor: CInt) throws {
|
||||||
precondition(MultiThreadedEventLoopGroup.currentEventLoop == nil,
|
|
||||||
"limitation in SwiftNIO: cannot bootstrap PipeChannel on EventLoop")
|
|
||||||
var s: stat = .init()
|
var s: stat = .init()
|
||||||
try withUnsafeMutablePointer(to: &s) { ptr in
|
try withUnsafeMutablePointer(to: &s) { ptr in
|
||||||
try Posix.fstat(descriptor: descriptor, outStat: ptr)
|
try Posix.fstat(descriptor: descriptor, outStat: ptr)
|
||||||
|
|
|
@ -39,6 +39,7 @@ extension BootstrapTest {
|
||||||
("testPreConnectedSocketSetsChannelOptionsBeforeChannelInitializer", testPreConnectedSocketSetsChannelOptionsBeforeChannelInitializer),
|
("testPreConnectedSocketSetsChannelOptionsBeforeChannelInitializer", testPreConnectedSocketSetsChannelOptionsBeforeChannelInitializer),
|
||||||
("testDatagramBootstrapSetsChannelOptionsBeforeChannelInitializer", testDatagramBootstrapSetsChannelOptionsBeforeChannelInitializer),
|
("testDatagramBootstrapSetsChannelOptionsBeforeChannelInitializer", testDatagramBootstrapSetsChannelOptionsBeforeChannelInitializer),
|
||||||
("testPipeBootstrapSetsChannelOptionsBeforeChannelInitializer", testPipeBootstrapSetsChannelOptionsBeforeChannelInitializer),
|
("testPipeBootstrapSetsChannelOptionsBeforeChannelInitializer", testPipeBootstrapSetsChannelOptionsBeforeChannelInitializer),
|
||||||
|
("testPipeBootstrapInEventLoop", testPipeBootstrapInEventLoop),
|
||||||
("testServerBootstrapAddsAcceptHandlerAfterServerChannelInitialiser", testServerBootstrapAddsAcceptHandlerAfterServerChannelInitialiser),
|
("testServerBootstrapAddsAcceptHandlerAfterServerChannelInitialiser", testServerBootstrapAddsAcceptHandlerAfterServerChannelInitialiser),
|
||||||
("testClientBootstrapValidatesWorkingELGsCorrectly", testClientBootstrapValidatesWorkingELGsCorrectly),
|
("testClientBootstrapValidatesWorkingELGsCorrectly", testClientBootstrapValidatesWorkingELGsCorrectly),
|
||||||
("testClientBootstrapRejectsNotWorkingELGsCorrectly", testClientBootstrapRejectsNotWorkingELGsCorrectly),
|
("testClientBootstrapRejectsNotWorkingELGsCorrectly", testClientBootstrapRejectsNotWorkingELGsCorrectly),
|
||||||
|
|
|
@ -389,6 +389,32 @@ class BootstrapTest: XCTestCase {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testPipeBootstrapInEventLoop() {
|
||||||
|
let testGrp = DispatchGroup()
|
||||||
|
testGrp.enter()
|
||||||
|
|
||||||
|
let eventLoop = self.group.next()
|
||||||
|
|
||||||
|
eventLoop.execute {
|
||||||
|
do {
|
||||||
|
let pipe = Pipe()
|
||||||
|
let readHandle = NIOFileHandle(descriptor: pipe.fileHandleForReading.fileDescriptor)
|
||||||
|
let writeHandle = NIOFileHandle(descriptor: pipe.fileHandleForWriting.fileDescriptor)
|
||||||
|
_ = NIOPipeBootstrap(group: self.group)
|
||||||
|
.withPipes(inputDescriptor: try readHandle.takeDescriptorOwnership(), outputDescriptor: try writeHandle.takeDescriptorOwnership())
|
||||||
|
.flatMap({ channel in
|
||||||
|
channel.close()
|
||||||
|
}).always({ _ in
|
||||||
|
testGrp.leave()
|
||||||
|
})
|
||||||
|
} catch {
|
||||||
|
XCTFail("Failed to bootstrap pipechannel in eventloop: \(error)")
|
||||||
|
testGrp.leave()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
testGrp.wait()
|
||||||
|
}
|
||||||
|
|
||||||
func testServerBootstrapAddsAcceptHandlerAfterServerChannelInitialiser() {
|
func testServerBootstrapAddsAcceptHandlerAfterServerChannelInitialiser() {
|
||||||
// It's unclear if this is the right solution, see https://github.com/apple/swift-nio/issues/1392
|
// It's unclear if this is the right solution, see https://github.com/apple/swift-nio/issues/1392
|
||||||
let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
|
let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
|
||||||
|
|
Loading…
Reference in New Issue