Skip to content

fix(ping): Fix panic in WASM caused by retrying on dial upgrade errors #5447

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 11 commits into from
Jun 10, 2024
3 changes: 3 additions & 0 deletions protocols/ping/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
- Use `web-time` instead of `instant`.
See [PR 5347](https://github.com/libp2p/rust-libp2p/pull/5347).

- Fix panic in WASM caused by retrying on dail errors.
See [PR 5447](https://github.com/libp2p/rust-libp2p/pull/5447).

## 0.44.1

- Impose `Sync` on `ping::Failure::Other`.
Expand Down
12 changes: 12 additions & 0 deletions protocols/ping/src/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,18 @@ impl Handler {
) {
self.outbound = None; // Request a new substream on the next `poll`.

// Timer is already polled and expired before substream request is initiated
// and will be polled again later on in our `poll` because we reset `self.outbound`.
//
// `futures-timer` allows an expired timer to be polled again and returns
// immediately `Poll::Ready`. However in its WASM implementation there is
// a bug that causes the expired timer to panic.
//
// This is a workaround until a proper fix is merged and released.
//
// See async-rs/futures-timer#74 and libp2p/rust-libp2p#5447 for more info.
self.interval.reset(Duration::new(0, 0));

let error = match error {
StreamUpgradeError::NegotiationFailed => {
debug_assert_eq!(self.state, State::Active);
Expand Down