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

[C++] Fix potential crash caused by AckGroupTracker's timer #8519

Merged

Conversation

BewareMyPower
Copy link
Contributor

@BewareMyPower BewareMyPower commented Nov 11, 2020

Motivation

The AckGroupingTrackerEnabled's timer callback only captures this, which is a weak reference to the AckGroupingTrackerEnabled instance. If the instance went out of the scope and destroyed, this would point to an invalid block.

Even if the destructor of AckGroupingTrackerEnabled cancels the timer, the callback may not be triggered immediately. There's still a possibility that when the callback is triggered, the error code is 0 but accessing to this is invalid. For example, there's a crash caused by the callback in production environment that is hard to reproduce:

#6 <signal handler called>
#7 0x00007fb4e67c5cb8 in ?? ()
#8 0x00007fb604981adb in operator() (ec=..., __closure=0x7fb52b0fb230)
   at /usr/local/src/apache-pulsar-microfocus/pulsar-client-cpp/lib/AckGroupingTrackerEnabled.cc:148
#9 operator() (this=0x7fb52b0fb230) at /usr/local/include/boost/asio/detail/bind_handler.hpp:47

Modifications

  • Use std::shared_ptr instead of std::unique_ptr for AckGroupingTrackerEnabled, then capture the shared pointer in timer callback's lambda expression to extend the lifetime of this.
  • Add start() method to AckGroupingTracker to avoid std::bad_weak_ptr because shared_from_this() in a constructor returns a null pointer.
  • Use std::weak_ptr to reference HandlerBase in case that the handler may be invalid when the timer callback is triggered.

Verifying this change

  • Make sure that the change passes the CI checks.

(Please pick either of the following options)

This change is a trivial rework / code cleanup without any test coverage.

@BewareMyPower BewareMyPower changed the title [C++] Fix potential crash caused by AckGroupTracker's timer [WIP][C++] Fix potential crash caused by AckGroupTracker's timer Nov 11, 2020
@BewareMyPower BewareMyPower changed the title [WIP][C++] Fix potential crash caused by AckGroupTracker's timer [C++] Fix potential crash caused by AckGroupTracker's timer Nov 11, 2020
@BewareMyPower BewareMyPower changed the title [C++] Fix potential crash caused by AckGroupTracker's timer [WIP][C++] Fix potential crash caused by AckGroupTracker's timer Nov 11, 2020
@BewareMyPower
Copy link
Contributor Author

/pulsarbot run-failure-checks

@BewareMyPower BewareMyPower changed the title [WIP][C++] Fix potential crash caused by AckGroupTracker's timer [C++] Fix potential crash caused by AckGroupTracker's timer Nov 11, 2020
@codelipenghui codelipenghui added this to the 2.7.0 milestone Nov 11, 2020
@codelipenghui codelipenghui merged commit cfa65d0 into apache:master Nov 12, 2020
@codelipenghui
Copy link
Contributor

/pulsarbot cherry-pick to branch-2.6

github-actions bot pushed a commit that referenced this pull request Nov 12, 2020
### Motivation

The `AckGroupingTrackerEnabled`'s timer callback only captures `this`, which is a weak reference to the `AckGroupingTrackerEnabled ` instance. If the instance went out of the scope and destroyed, `this` would point to an invalid block.

Even if the destructor of `AckGroupingTrackerEnabled` cancels the timer, the callback may not be triggered immediately. There's still a possibility that when the callback is triggered, the error code is 0 but accessing to `this` is invalid. For example, there's a crash caused by the callback in production environment that is hard to reproduce:

```
#6 <signal handler called>
#7 0x00007fb4e67c5cb8 in ?? ()
#8 0x00007fb604981adb in operator() (ec=..., __closure=0x7fb52b0fb230)
   at /usr/local/src/apache-pulsar-microfocus/pulsar-client-cpp/lib/AckGroupingTrackerEnabled.cc:148
#9 operator() (this=0x7fb52b0fb230) at /usr/local/include/boost/asio/detail/bind_handler.hpp:47
```

### Modifications

- Use `std::shared_ptr` instead of `std::unique_ptr` for `AckGroupingTrackerEnabled`, then capture the shared pointer in timer callback's lambda expression to extend the lifetime of `this`.
- Add `start()` method to `AckGroupingTracker` to avoid `std::bad_weak_ptr` because `shared_from_this()` in a constructor returns a null pointer.
- Use `std::weak_ptr` to reference `HandlerBase` in case that the handler may be invalid when the timer callback is triggered.
codelipenghui pushed a commit that referenced this pull request Nov 12, 2020
### Motivation

The `AckGroupingTrackerEnabled`'s timer callback only captures `this`, which is a weak reference to the `AckGroupingTrackerEnabled ` instance. If the instance went out of the scope and destroyed, `this` would point to an invalid block.

Even if the destructor of `AckGroupingTrackerEnabled` cancels the timer, the callback may not be triggered immediately. There's still a possibility that when the callback is triggered, the error code is 0 but accessing to `this` is invalid. For example, there's a crash caused by the callback in production environment that is hard to reproduce:

```
#6 <signal handler called>
#7 0x00007fb4e67c5cb8 in ?? ()
#8 0x00007fb604981adb in operator() (ec=..., __closure=0x7fb52b0fb230)
   at /usr/local/src/apache-pulsar-microfocus/pulsar-client-cpp/lib/AckGroupingTrackerEnabled.cc:148
#9 operator() (this=0x7fb52b0fb230) at /usr/local/include/boost/asio/detail/bind_handler.hpp:47
```

### Modifications

- Use `std::shared_ptr` instead of `std::unique_ptr` for `AckGroupingTrackerEnabled`, then capture the shared pointer in timer callback's lambda expression to extend the lifetime of `this`.
- Add `start()` method to `AckGroupingTracker` to avoid `std::bad_weak_ptr` because `shared_from_this()` in a constructor returns a null pointer.
- Use `std::weak_ptr` to reference `HandlerBase` in case that the handler may be invalid when the timer callback is triggered.

(cherry picked from commit cfa65d0)
@codelipenghui
Copy link
Contributor

cherry-picked to branch-2.6

codelipenghui pushed a commit to streamnative/pulsar-archived that referenced this pull request Nov 13, 2020
)

### Motivation

The `AckGroupingTrackerEnabled`'s timer callback only captures `this`, which is a weak reference to the `AckGroupingTrackerEnabled ` instance. If the instance went out of the scope and destroyed, `this` would point to an invalid block.

Even if the destructor of `AckGroupingTrackerEnabled` cancels the timer, the callback may not be triggered immediately. There's still a possibility that when the callback is triggered, the error code is 0 but accessing to `this` is invalid. For example, there's a crash caused by the callback in production environment that is hard to reproduce:

```
#6 <signal handler called>
#7 0x00007fb4e67c5cb8 in ?? ()
#8 0x00007fb604981adb in operator() (ec=..., __closure=0x7fb52b0fb230)
   at /usr/local/src/apache-pulsar-microfocus/pulsar-client-cpp/lib/AckGroupingTrackerEnabled.cc:148
#9 operator() (this=0x7fb52b0fb230) at /usr/local/include/boost/asio/detail/bind_handler.hpp:47
```

### Modifications

- Use `std::shared_ptr` instead of `std::unique_ptr` for `AckGroupingTrackerEnabled`, then capture the shared pointer in timer callback's lambda expression to extend the lifetime of `this`.
- Add `start()` method to `AckGroupingTracker` to avoid `std::bad_weak_ptr` because `shared_from_this()` in a constructor returns a null pointer.
- Use `std::weak_ptr` to reference `HandlerBase` in case that the handler may be invalid when the timer callback is triggered.

(cherry picked from commit cfa65d0)
(cherry picked from commit 98591c4)
flowchartsman pushed a commit to flowchartsman/pulsar that referenced this pull request Nov 17, 2020
)

### Motivation

The `AckGroupingTrackerEnabled`'s timer callback only captures `this`, which is a weak reference to the `AckGroupingTrackerEnabled ` instance. If the instance went out of the scope and destroyed, `this` would point to an invalid block.

Even if the destructor of `AckGroupingTrackerEnabled` cancels the timer, the callback may not be triggered immediately. There's still a possibility that when the callback is triggered, the error code is 0 but accessing to `this` is invalid. For example, there's a crash caused by the callback in production environment that is hard to reproduce:

```
#6 <signal handler called>
apache#7 0x00007fb4e67c5cb8 in ?? ()
apache#8 0x00007fb604981adb in operator() (ec=..., __closure=0x7fb52b0fb230)
   at /usr/local/src/apache-pulsar-microfocus/pulsar-client-cpp/lib/AckGroupingTrackerEnabled.cc:148
apache#9 operator() (this=0x7fb52b0fb230) at /usr/local/include/boost/asio/detail/bind_handler.hpp:47
```

### Modifications

- Use `std::shared_ptr` instead of `std::unique_ptr` for `AckGroupingTrackerEnabled`, then capture the shared pointer in timer callback's lambda expression to extend the lifetime of `this`.
- Add `start()` method to `AckGroupingTracker` to avoid `std::bad_weak_ptr` because `shared_from_this()` in a constructor returns a null pointer.
- Use `std::weak_ptr` to reference `HandlerBase` in case that the handler may be invalid when the timer callback is triggered.
saosir pushed a commit to saosir/pulsar that referenced this pull request Nov 30, 2020
…mer(issue like #apache#8519)

### Motivation

- pulsar-client-cpp Consumer do AcknowledgeCumulative just clean up `msgId`, not <= `msgId` in  `UnAckedMessageTrackerEnabled::removeMessagesTill`
- potential crash caused by UnAckedMessageTrackerEnabled's timer(see issue like apache#8519)

### Modifications

- When do AcknowledgeCumulative from application, earse <= `msgId` in UnAckedMessageTrackerEnabled, avoid redeliver unnecessary unacknowledged messages to Broker
- Use std::shared_ptr instead of std::unique_ptr for UnAckedMessageTrackerEnabled
- add `start()`, `close()` method to `UnAckedMessageTrackerEnabled` solve same issue see apache#8519
- add `isEmpty()`, `size()` method to `UnAckedMessageTrackerEnabled` for checking of test case
- when close `UnAckedMessageTrackerEnabled` and `AckGroupingTrackerEnabled`, reset shared_ptr `timer_`
- add unit test for `UnAckedMessageTrackerEnabled`
saosir pushed a commit to saosir/pulsar that referenced this pull request Nov 30, 2020
…mer(issue like #apache#8519)

- pulsar-client-cpp Consumer do AcknowledgeCumulative just clean up `msgId`, not <= `msgId` in  `UnAckedMessageTrackerEnabled::removeMessagesTill`
- potential crash caused by UnAckedMessageTrackerEnabled's timer(see issue like apache#8519)

- When do AcknowledgeCumulative from application, earse <= `msgId` in UnAckedMessageTrackerEnabled, avoid redeliver unnecessary unacknowledged messages to Broker
- Use std::shared_ptr instead of std::unique_ptr for UnAckedMessageTrackerEnabled
- add `start()`, `close()` method to `UnAckedMessageTrackerEnabled` solve same issue see apache#8519
- add `isEmpty()`, `size()` method to `UnAckedMessageTrackerEnabled` for checking of test case
- when close `UnAckedMessageTrackerEnabled` and `AckGroupingTrackerEnabled`, reset shared_ptr `timer_`
- add unit test for `UnAckedMessageTrackerEnabled`
saosir added a commit to saosir/pulsar that referenced this pull request Nov 30, 2020
…mer(issue like #apache#8519)

- pulsar-client-cpp Consumer do AcknowledgeCumulative just clean up `msgId`, not <= `msgId` in  `UnAckedMessageTrackerEnabled::removeMessagesTill`
- potential crash caused by UnAckedMessageTrackerEnabled's timer(see issue like apache#8519)

- When do AcknowledgeCumulative from application, earse <= `msgId` in UnAckedMessageTrackerEnabled, avoid redeliver unnecessary unacknowledged messages to Broker
- Use std::shared_ptr instead of std::unique_ptr for UnAckedMessageTrackerEnabled
- add `start()`, `close()` method to `UnAckedMessageTrackerEnabled` solve same issue see apache#8519
- add `isEmpty()`, `size()` method to `UnAckedMessageTrackerEnabled` for checking of test case
- when close `UnAckedMessageTrackerEnabled` and `AckGroupingTrackerEnabled`, reset shared_ptr `timer_`
- add unit test for `UnAckedMessageTrackerEnabled`
[C++] Fix potential crash caused by UnAckedMessageTrackerEnabled's timer(issue like #apache#8519)

- pulsar-client-cpp Consumer do AcknowledgeCumulative just clean up `msgId`, not <= `msgId` in  `UnAckedMessageTrackerEnabled::removeMessagesTill`
- potential crash caused by UnAckedMessageTrackerEnabled's timer(see issue like apache#8519)

- When do AcknowledgeCumulative from application, earse <= `msgId` in UnAckedMessageTrackerEnabled, avoid redeliver unnecessary unacknowledged messages to Broker
- Use std::shared_ptr instead of std::unique_ptr for UnAckedMessageTrackerEnabled
- add `start()`, `close()` method to `UnAckedMessageTrackerEnabled` solve same issue see apache#8519
- add `isEmpty()`, `size()` method to `UnAckedMessageTrackerEnabled` for checking of test case
- when close `UnAckedMessageTrackerEnabled` and `AckGroupingTrackerEnabled`, reset shared_ptr `timer_`
- add unit test for `UnAckedMessageTrackerEnabled`
saosir added a commit to saosir/pulsar that referenced this pull request Nov 30, 2020
…mer(issue like #apache#8519)

- pulsar-client-cpp Consumer do AcknowledgeCumulative just clean up `msgId`, not <= `msgId` in  `UnAckedMessageTrackerEnabled::removeMessagesTill`
- potential crash caused by UnAckedMessageTrackerEnabled's timer(see issue like apache#8519)

- When do AcknowledgeCumulative from application, earse <= `msgId` in UnAckedMessageTrackerEnabled, avoid redeliver unnecessary unacknowledged messages to Broker
- Use std::shared_ptr instead of std::unique_ptr for UnAckedMessageTrackerEnabled
- add `start()`, `close()` method to `UnAckedMessageTrackerEnabled` solve same issue see apache#8519
- add `isEmpty()`, `size()` method to `UnAckedMessageTrackerEnabled` for checking of test case
- when close `UnAckedMessageTrackerEnabled` and `AckGroupingTrackerEnabled`, reset shared_ptr `timer_`
- add unit test for `UnAckedMessageTrackerEnabled`
[C++] Fix potential crash caused by UnAckedMessageTrackerEnabled's timer(issue like #apache#8519)

- pulsar-client-cpp Consumer do AcknowledgeCumulative just clean up `msgId`, not <= `msgId` in  `UnAckedMessageTrackerEnabled::removeMessagesTill`
- potential crash caused by UnAckedMessageTrackerEnabled's timer(see issue like apache#8519)

- When do AcknowledgeCumulative from application, earse <= `msgId` in UnAckedMessageTrackerEnabled, avoid redeliver unnecessary unacknowledged messages to Broker
- Use std::shared_ptr instead of std::unique_ptr for UnAckedMessageTrackerEnabled
- add `start()`, `close()` method to `UnAckedMessageTrackerEnabled` solve same issue see apache#8519
- add `isEmpty()`, `size()` method to `UnAckedMessageTrackerEnabled` for checking of test case
- when close `UnAckedMessageTrackerEnabled` and `AckGroupingTrackerEnabled`, reset shared_ptr `timer_`
- add unit test for `UnAckedMessageTrackerEnabled`
saosir added a commit to saosir/pulsar that referenced this pull request Nov 30, 2020
…mer(issue like #apache#8519)

- pulsar-client-cpp Consumer do AcknowledgeCumulative just clean up `msgId`, not <= `msgId` in  `UnAckedMessageTrackerEnabled::removeMessagesTill`
- potential crash caused by UnAckedMessageTrackerEnabled's timer(see issue like apache#8519)

- When do AcknowledgeCumulative from application, earse <= `msgId` in UnAckedMessageTrackerEnabled, avoid redeliver unnecessary unacknowledged messages to Broker
- Use std::shared_ptr instead of std::unique_ptr for UnAckedMessageTrackerEnabled
- add `start()`, `close()` method to `UnAckedMessageTrackerEnabled` solve same issue see apache#8519
- add `isEmpty()`, `size()` method to `UnAckedMessageTrackerEnabled` for checking of test case
- when close `UnAckedMessageTrackerEnabled` and `AckGroupingTrackerEnabled`, reset shared_ptr `timer_`
- add unit test for `UnAckedMessageTrackerEnabled`
[C++] Fix potential crash caused by UnAckedMessageTrackerEnabled's timer(issue like #apache#8519)

- pulsar-client-cpp Consumer do AcknowledgeCumulative just clean up `msgId`, not <= `msgId` in  `UnAckedMessageTrackerEnabled::removeMessagesTill`
- potential crash caused by UnAckedMessageTrackerEnabled's timer(see issue like apache#8519)

- When do AcknowledgeCumulative from application, earse <= `msgId` in UnAckedMessageTrackerEnabled, avoid redeliver unnecessary unacknowledged messages to Broker
- Use std::shared_ptr instead of std::unique_ptr for UnAckedMessageTrackerEnabled
- add `start()`, `close()` method to `UnAckedMessageTrackerEnabled` solve same issue see apache#8519
- add `isEmpty()`, `size()` method to `UnAckedMessageTrackerEnabled` for checking of test case
- when close `UnAckedMessageTrackerEnabled` and `AckGroupingTrackerEnabled`, reset shared_ptr `timer_`
- add unit test for `UnAckedMessageTrackerEnabled`
saosir added a commit to saosir/pulsar that referenced this pull request Nov 30, 2020
…mer(issue like #apache#8519)

- pulsar-client-cpp Consumer do AcknowledgeCumulative just clean up `msgId`, not <= `msgId` in  `UnAckedMessageTrackerEnabled::removeMessagesTill`
- potential crash caused by UnAckedMessageTrackerEnabled's timer(see issue like apache#8519)

- When do AcknowledgeCumulative from application, earse <= `msgId` in UnAckedMessageTrackerEnabled, avoid redeliver unnecessary unacknowledged messages to Broker
- Use std::shared_ptr instead of std::unique_ptr for UnAckedMessageTrackerEnabled
- add `start()`, `close()` method to `UnAckedMessageTrackerEnabled` solve same issue see apache#8519
- add `isEmpty()`, `size()` method to `UnAckedMessageTrackerEnabled` for checking of test case
- when close `UnAckedMessageTrackerEnabled` and `AckGroupingTrackerEnabled`, reset shared_ptr `timer_`
- add unit test for `UnAckedMessageTrackerEnabled`
[C++] Fix potential crash caused by UnAckedMessageTrackerEnabled's timer(issue like #apache#8519)

- pulsar-client-cpp Consumer do AcknowledgeCumulative just clean up `msgId`, not <= `msgId` in  `UnAckedMessageTrackerEnabled::removeMessagesTill`
- potential crash caused by UnAckedMessageTrackerEnabled's timer(see issue like apache#8519)

- When do AcknowledgeCumulative from application, earse <= `msgId` in UnAckedMessageTrackerEnabled, avoid redeliver unnecessary unacknowledged messages to Broker
- Use std::shared_ptr instead of std::unique_ptr for UnAckedMessageTrackerEnabled
- add `start()`, `close()` method to `UnAckedMessageTrackerEnabled` solve same issue see apache#8519
- add `isEmpty()`, `size()` method to `UnAckedMessageTrackerEnabled` for checking of test case
- when close `UnAckedMessageTrackerEnabled` and `AckGroupingTrackerEnabled`, reset shared_ptr `timer_`
- add unit test for `UnAckedMessageTrackerEnabled`
@BewareMyPower BewareMyPower deleted the bewaremypower/fix-cpp-ack-group branch December 2, 2020 07:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants