diff --git a/protocols/ping/CHANGELOG.md b/protocols/ping/CHANGELOG.md index 507bf7532ba..7c7d7f3a54f 100644 --- a/protocols/ping/CHANGELOG.md +++ b/protocols/ping/CHANGELOG.md @@ -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 dial upgrade errors. + See [PR 5447](https://github.com/libp2p/rust-libp2p/pull/5447). + ## 0.44.1 - Impose `Sync` on `ping::Failure::Other`. diff --git a/protocols/ping/src/handler.rs b/protocols/ping/src/handler.rs index b9bd25c52ea..2816cdc4048 100644 --- a/protocols/ping/src/handler.rs +++ b/protocols/ping/src/handler.rs @@ -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 libp2p/rust-libp2p#5447 for more info. + // + // TODO: remove when async-rs/futures-timer#74 gets merged. + self.interval.reset(Duration::new(0, 0)); + let error = match error { StreamUpgradeError::NegotiationFailed => { debug_assert_eq!(self.state, State::Active);