Skip to content

Fix NettyChannelTracker race condition when tracking new channels #904

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 3, 2021

Conversation

injectives
Copy link
Contributor

This update fixes an issue when SimpleChannelPool may invoke the channelAcquired method before the channelCreated method is called. Since it violates NettyChannelTracker contract, it may result in runtime failures.

See the following for details:

@startuml
T1 -> SimpleChannelPool: acquireHealthyFromPoolOrNew
activate SimpleChannelPool

SimpleChannelPool -> NettyChannelPool: connectChannel
activate NettyChannelPool

NettyChannelPool -> ChannelFuture: addListener
activate ChannelFuture

ChannelFuture --> NettyChannelPool:
deactivate ChannelFuture

NettyChannelPool --> SimpleChannelPool:
deactivate NettyChannelPool

T2 -> ChannelFuture: setSuccess
activate ChannelFuture

ChannelFuture -> ChannelFuture: done
activate ChannelFuture

ChannelFuture --> ChannelFuture:
deactivate ChannelFuture

SimpleChannelPool -> ChannelFuture: isDone
activate ChannelFuture

ChannelFuture --> SimpleChannelPool:
deactivate ChannelFuture

alt isDone case
    SimpleChannelPool -> NettyChannelTracker: channelAcquired
    activate NettyChannelTracker

    NettyChannelTracker --> SimpleChannelPool:
    deactivate NettyChannelTracker
end

SimpleChannelPool --> T1:
deactivate SimpleChannelPool

ChannelFuture -> NettyChannelTracker: channelCreated
activate NettyChannelTracker

NettyChannelTracker -> ChannelFuture:
deactivate NettyChannelTracker

ChannelFuture -> T2:
deactivate ChannelFuture
@enduml

This update fixes an issue when `SimpleChannelPool` may invoke the `channelAcquired` method before the `channelCreated` method is called. Since it violates `NettyChannelTracker` contract, it may result in runtime failures.

See the following for details:
```
@startuml
T1 -> SimpleChannelPool: acquireHealthyFromPoolOrNew
activate SimpleChannelPool

SimpleChannelPool -> NettyChannelPool: connectChannel
activate NettyChannelPool

NettyChannelPool -> ChannelFuture: addListener
activate ChannelFuture

ChannelFuture --> NettyChannelPool:
deactivate ChannelFuture

NettyChannelPool --> SimpleChannelPool:
deactivate NettyChannelPool

T2 -> ChannelFuture: setSuccess
activate ChannelFuture

ChannelFuture -> ChannelFuture: done
activate ChannelFuture

ChannelFuture --> ChannelFuture:
deactivate ChannelFuture

SimpleChannelPool -> ChannelFuture: isDone
activate ChannelFuture

ChannelFuture --> SimpleChannelPool:
deactivate ChannelFuture

alt isDone case
    SimpleChannelPool -> NettyChannelTracker: channelAcquired
    activate NettyChannelTracker

    NettyChannelTracker --> SimpleChannelPool:
    deactivate NettyChannelTracker
end

SimpleChannelPool --> T1:
deactivate SimpleChannelPool

ChannelFuture -> NettyChannelTracker: channelCreated
activate NettyChannelTracker

NettyChannelTracker -> ChannelFuture:
deactivate NettyChannelTracker

ChannelFuture -> T2:
deactivate ChannelFuture
@enduml
```
@injectives injectives requested a review from michael-simons June 2, 2021 22:18
@michael-simons
Copy link
Contributor

Since it violates NettyChannelTracker contract, it may result in runtime failures.

just to be sure, this is about the old situation?

Copy link
Contributor

@michael-simons michael-simons left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.

A couple of things:

  • I wonder if we can reproduce the failures locally when metrics are turned on
  • did we actually make the failures happen more often because the tracker is now thread safe after the previous fix attempts?
  • If this works I like it to be backported to 4.2 and 4.1 but I can do that as well.

@injectives
Copy link
Contributor Author

Since it violates NettyChannelTracker contract, it may result in runtime failures.

just to be sure, this is about the old situation?

This is about the case that this change tries to fix.

@injectives
Copy link
Contributor Author

  • I wonder if we can reproduce the failures locally when metrics are turned on

I tried setting up a simple case on local environment, but could not reproduce this. Given that this is effectively a race condition, it might be tricky to reproduce. Fortunately, we have some CI builds that may help us with this.

@injectives
Copy link
Contributor Author

injectives commented Jun 3, 2021

  • did we actually make the failures happen more often because the tracker is now thread safe after the previous fix attempts?

This change did not seem to make a negative impact on my local environment, it will be verified further in CI builds.

@injectives
Copy link
Contributor Author

  • If this works I like it to be backported to 4.2 and 4.1 but I can do that as well.

Since it fixes a race condition that may occur, it makes sense to backport it.

@injectives
Copy link
Contributor Author

Looks good to me.

Thanks 👍

@injectives injectives merged commit 9813663 into neo4j:4.3 Jun 3, 2021
@injectives injectives deleted the feature/channel-tracker-fix branch June 3, 2021 09:29
injectives added a commit to injectives/neo4j-java-driver that referenced this pull request Jun 4, 2021
…o4j#904)

This update fixes an issue when `SimpleChannelPool` may invoke the `channelAcquired` method before the `channelCreated` method is called. Since it violates `NettyChannelTracker` contract, it may result in runtime failures.

See the following for details:
```
@startuml
T1 -> SimpleChannelPool: acquireHealthyFromPoolOrNew
activate SimpleChannelPool

SimpleChannelPool -> NettyChannelPool: connectChannel
activate NettyChannelPool

NettyChannelPool -> ChannelFuture: addListener
activate ChannelFuture

ChannelFuture --> NettyChannelPool:
deactivate ChannelFuture

NettyChannelPool --> SimpleChannelPool:
deactivate NettyChannelPool

T2 -> ChannelFuture: setSuccess
activate ChannelFuture

ChannelFuture -> ChannelFuture: done
activate ChannelFuture

ChannelFuture --> ChannelFuture:
deactivate ChannelFuture

SimpleChannelPool -> ChannelFuture: isDone
activate ChannelFuture

ChannelFuture --> SimpleChannelPool:
deactivate ChannelFuture

alt isDone case
    SimpleChannelPool -> NettyChannelTracker: channelAcquired
    activate NettyChannelTracker

    NettyChannelTracker --> SimpleChannelPool:
    deactivate NettyChannelTracker
end

SimpleChannelPool --> T1:
deactivate SimpleChannelPool

ChannelFuture -> NettyChannelTracker: channelCreated
activate NettyChannelTracker

NettyChannelTracker -> ChannelFuture:
deactivate NettyChannelTracker

ChannelFuture -> T2:
deactivate ChannelFuture
@enduml
```
injectives added a commit to injectives/neo4j-java-driver that referenced this pull request Jun 4, 2021
…o4j#904)

This update fixes an issue when `SimpleChannelPool` may invoke the `channelAcquired` method before the `channelCreated` method is called. Since it violates `NettyChannelTracker` contract, it may result in runtime failures.

See the following for details:
```
@startuml
T1 -> SimpleChannelPool: acquireHealthyFromPoolOrNew
activate SimpleChannelPool

SimpleChannelPool -> NettyChannelPool: connectChannel
activate NettyChannelPool

NettyChannelPool -> ChannelFuture: addListener
activate ChannelFuture

ChannelFuture --> NettyChannelPool:
deactivate ChannelFuture

NettyChannelPool --> SimpleChannelPool:
deactivate NettyChannelPool

T2 -> ChannelFuture: setSuccess
activate ChannelFuture

ChannelFuture -> ChannelFuture: done
activate ChannelFuture

ChannelFuture --> ChannelFuture:
deactivate ChannelFuture

SimpleChannelPool -> ChannelFuture: isDone
activate ChannelFuture

ChannelFuture --> SimpleChannelPool:
deactivate ChannelFuture

alt isDone case
    SimpleChannelPool -> NettyChannelTracker: channelAcquired
    activate NettyChannelTracker

    NettyChannelTracker --> SimpleChannelPool:
    deactivate NettyChannelTracker
end

SimpleChannelPool --> T1:
deactivate SimpleChannelPool

ChannelFuture -> NettyChannelTracker: channelCreated
activate NettyChannelTracker

NettyChannelTracker -> ChannelFuture:
deactivate NettyChannelTracker

ChannelFuture -> T2:
deactivate ChannelFuture
@enduml
```
injectives added a commit that referenced this pull request Jun 4, 2021
…) (#905)

This update fixes an issue when `SimpleChannelPool` may invoke the `channelAcquired` method before the `channelCreated` method is called. Since it violates `NettyChannelTracker` contract, it may result in runtime failures.

See the following for details:
```
@startuml
T1 -> SimpleChannelPool: acquireHealthyFromPoolOrNew
activate SimpleChannelPool

SimpleChannelPool -> NettyChannelPool: connectChannel
activate NettyChannelPool

NettyChannelPool -> ChannelFuture: addListener
activate ChannelFuture

ChannelFuture --> NettyChannelPool:
deactivate ChannelFuture

NettyChannelPool --> SimpleChannelPool:
deactivate NettyChannelPool

T2 -> ChannelFuture: setSuccess
activate ChannelFuture

ChannelFuture -> ChannelFuture: done
activate ChannelFuture

ChannelFuture --> ChannelFuture:
deactivate ChannelFuture

SimpleChannelPool -> ChannelFuture: isDone
activate ChannelFuture

ChannelFuture --> SimpleChannelPool:
deactivate ChannelFuture

alt isDone case
    SimpleChannelPool -> NettyChannelTracker: channelAcquired
    activate NettyChannelTracker

    NettyChannelTracker --> SimpleChannelPool:
    deactivate NettyChannelTracker
end

SimpleChannelPool --> T1:
deactivate SimpleChannelPool

ChannelFuture -> NettyChannelTracker: channelCreated
activate NettyChannelTracker

NettyChannelTracker -> ChannelFuture:
deactivate NettyChannelTracker

ChannelFuture -> T2:
deactivate ChannelFuture
@enduml
```
injectives added a commit that referenced this pull request Jun 7, 2021
…) (#906)

This update fixes an issue when `SimpleChannelPool` may invoke the `channelAcquired` method before the `channelCreated` method is called. Since it violates `NettyChannelTracker` contract, it may result in runtime failures.

See the following for details:
```
@startuml
T1 -> SimpleChannelPool: acquireHealthyFromPoolOrNew
activate SimpleChannelPool

SimpleChannelPool -> NettyChannelPool: connectChannel
activate NettyChannelPool

NettyChannelPool -> ChannelFuture: addListener
activate ChannelFuture

ChannelFuture --> NettyChannelPool:
deactivate ChannelFuture

NettyChannelPool --> SimpleChannelPool:
deactivate NettyChannelPool

T2 -> ChannelFuture: setSuccess
activate ChannelFuture

ChannelFuture -> ChannelFuture: done
activate ChannelFuture

ChannelFuture --> ChannelFuture:
deactivate ChannelFuture

SimpleChannelPool -> ChannelFuture: isDone
activate ChannelFuture

ChannelFuture --> SimpleChannelPool:
deactivate ChannelFuture

alt isDone case
    SimpleChannelPool -> NettyChannelTracker: channelAcquired
    activate NettyChannelTracker

    NettyChannelTracker --> SimpleChannelPool:
    deactivate NettyChannelTracker
end

SimpleChannelPool --> T1:
deactivate SimpleChannelPool

ChannelFuture -> NettyChannelTracker: channelCreated
activate NettyChannelTracker

NettyChannelTracker -> ChannelFuture:
deactivate NettyChannelTracker

ChannelFuture -> T2:
deactivate ChannelFuture
@enduml
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants