mirror of
https://github.com/corda/corda.git
synced 2025-02-21 09:51:57 +00:00
rpc: Fix deadlock caused by deliver() and close()
This commit is contained in:
parent
a394adbb44
commit
60520412c8
@ -284,6 +284,10 @@ class CordaRPCClientImpl(private val session: ClientSession,
|
||||
private val rootShared = root.doOnUnsubscribe { close() }.share()
|
||||
|
||||
// This could be made more efficient by using a specialised IntMap
|
||||
/**
|
||||
* When handling this map we synchronise on it explicitly instead of on [this], otherwise there is a race
|
||||
* condition between close() and deliver()
|
||||
*/
|
||||
private val observables = HashMap<Int, Observable<Any>>()
|
||||
|
||||
private var consumer: ClientConsumer? = null
|
||||
@ -320,8 +324,8 @@ class CordaRPCClientImpl(private val session: ClientSession,
|
||||
}
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun getForHandle(handle: Int): Observable<Any> {
|
||||
synchronized(observables) {
|
||||
return observables.getOrPut(handle) {
|
||||
/**
|
||||
* Note that the order of bufferUntilSubscribed() -> dematerialize() is very important here.
|
||||
@ -340,13 +344,14 @@ class CordaRPCClientImpl(private val session: ClientSession,
|
||||
rootShared.filter { it.forHandle == handle }.map { it.what }.bufferUntilSubscribed().dematerialize<Any>().doOnSubscribe { refCountUp() }.doOnUnsubscribe { refCountDown() }.share()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun deliver(msg: ClientMessage) {
|
||||
msg.acknowledge()
|
||||
val kryo = createRPCKryo(observableSerializer = observableDeserializer)
|
||||
val received: MarshalledObservation = msg.deserialize(kryo)
|
||||
rpcLog.debug { "<- Observable [$rpcName] <- Received $received" }
|
||||
synchronized(this) {
|
||||
synchronized(observables) {
|
||||
// Force creation of the buffer if it doesn't already exist.
|
||||
getForHandle(received.forHandle)
|
||||
root.onNext(received)
|
||||
|
Loading…
x
Reference in New Issue
Block a user