Skip to content

TCPClient in json-rpc isn't thread-safe #37

@weissi

Description

@weissi

public func connect(host: String, port: Int) -> EventLoopFuture<TCPClient> {
assert(.initializing == self.state)
let bootstrap = ClientBootstrap(group: self.group)
.channelOption(ChannelOptions.socket(SocketOptionLevel(SOL_SOCKET), SO_REUSEADDR), value: 1)
.channelInitializer { channel in
return channel.pipeline.addTimeoutHandlers(self.config.timeout)
.flatMap {
channel.pipeline.addFramingHandlers(framing: self.config.framing)
}.flatMap {
channel.pipeline.addHandlers([
CodableCodec<JSONResponse, JSONRequest>(),
Handler(),
])
}
}
self.state = .connecting("\(host):\(port)")
return bootstrap.connect(host: host, port: port).flatMap { channel in
self.channel = channel
self.state = .connected
return channel.eventLoop.makeSucceededFuture(self)
}
}
public func disconnect() -> EventLoopFuture<Void> {
if .connected != self.state {
return self.group.next().makeFailedFuture(ClientError.notReady)
}
guard let channel = self.channel else {
return self.group.next().makeFailedFuture(ClientError.notReady)
}
self.state = .disconnecting
channel.closeFuture.whenComplete { _ in
self.state = .disconnected
}
channel.close(promise: nil)
return channel.closeFuture
}
public func call(method: String, params: RPCObject) -> EventLoopFuture<Result> {

Thanks to @wlisac for the report.

At least TCPClient is very thread unsafe and really needs fixing. Without synchronisation, state is read/written to from different threads.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions