Skip to content
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

Fix crash when removing connection from the pool #347

Conversation

BewareMyPower
Copy link
Contributor

Fixes #346

Motivation

#336 changes the key of the ClientConnection in ConnectionPool, while in ClientConnection::close, it still passes the old key (logical address) to ConnectionPool::remove, which results in the connection could never be removed and destroyed until being deleted as a stale connection.

What's worse, if the key does not exist, the iterator returned by std::map::find will still be dereferenced, which might cause crash in some platforms. See

auto it = pool_.find(key);
if (it->second.get() == value) {

Modifications

  • Avoid dereferencing the iterator if it's invalid in ConnectionPool::remove.
  • Store the key suffix in ClientConnection and pass the correct key to ConnectionPool::remove in ClientConnection::close
  • Add ClientTest.testConnectionClose to verify ClientConnection::close can remove itself from the pool and the connection will be destroyed eventually.

@BewareMyPower BewareMyPower self-assigned this Nov 16, 2023
@BewareMyPower BewareMyPower added the bug Something isn't working label Nov 16, 2023
@BewareMyPower
Copy link
Contributor Author

More context: https://stackoverflow.com/questions/16267615/is-second-defined-for-iterator-stdmapend

Dereferencing an iterator that points to the end of a STL container is UB.

Fixes apache#346

### Motivation

apache#336 changes the key of
the `ClientConnection` in `ConnectionPool`, while in
`ClientConnection::close`, it still passes the old key (logical address)
to `ConnectionPool::remove`, which results in the connection could never
be removed and destroyed until being deleted as a stale connection.

What's worse, if the key does not exist, the iterator returned by
`std::map::find` will still be dereferenced, which might cause crash in
some platforms. See
https://github.com/apache/pulsar-client-cpp/blob/8d32fd254e294d1fabba73aed70115a434b341ef/lib/ConnectionPool.cc#L122-L123

### Modifications

- Avoid dereferencing the iterator if it's invalid in
  `ConnectionPool::remove`.
- Store the key suffix in `ClientConnection` and pass the correct key to
  `ConnectionPool::remove` in `ClientConnection::close`
- Add `ClientTest.testConnectionClose` to verify
  `ClientConnection::close` can remove itself from the pool and the
  connection will be destroyed eventually.
@BewareMyPower BewareMyPower force-pushed the bewaremypower/fix-crash-cnx-per-broker branch from 270d36c to f90a9c3 Compare November 16, 2023 04:50
@BewareMyPower BewareMyPower added this to the 3.4.1 milestone Nov 16, 2023
@BewareMyPower BewareMyPower merged commit 6d47e94 into apache:main Nov 17, 2023
11 checks passed
@BewareMyPower BewareMyPower deleted the bewaremypower/fix-crash-cnx-per-broker branch November 17, 2023 02:31
BewareMyPower added a commit that referenced this pull request Nov 17, 2023
Fixes #346

### Motivation

#336 changes the key of
the `ClientConnection` in `ConnectionPool`, while in
`ClientConnection::close`, it still passes the old key (logical address)
to `ConnectionPool::remove`, which results in the connection could never
be removed and destroyed until being deleted as a stale connection.

What's worse, if the key does not exist, the iterator returned by
`std::map::find` will still be dereferenced, which might cause crash in
some platforms. See
https://github.com/apache/pulsar-client-cpp/blob/8d32fd254e294d1fabba73aed70115a434b341ef/lib/ConnectionPool.cc#L122-L123

### Modifications

- Avoid dereferencing the iterator if it's invalid in
  `ConnectionPool::remove`.
- Store the key suffix in `ClientConnection` and pass the correct key to
  `ConnectionPool::remove` in `ClientConnection::close`
- Add `ClientTest.testConnectionClose` to verify
  `ClientConnection::close` can remove itself from the pool and the
  connection will be destroyed eventually.

(cherry picked from commit 6d47e94)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Bug] ConnectionPool::remove Crash
2 participants