Skip to content

Commit 197b3ec

Browse files
committed
Don't crash when acknowledging a cancelled ping.
Fix #1566.
1 parent d852df7 commit 197b3ec

File tree

3 files changed

+25
-3
lines changed

3 files changed

+25
-3
lines changed

src/websockets/asyncio/connection.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -750,7 +750,8 @@ def acknowledge_pings(self, data: bytes) -> None:
750750
for ping_id, (pong_waiter, ping_timestamp) in self.pong_waiters.items():
751751
ping_ids.append(ping_id)
752752
latency = pong_timestamp - ping_timestamp
753-
pong_waiter.set_result(latency)
753+
if not pong_waiter.done():
754+
pong_waiter.set_result(latency)
754755
if ping_id == data:
755756
self.latency = latency
756757
break

tests/asyncio/test_connection.py

+22-1
Original file line numberDiff line numberDiff line change
@@ -892,6 +892,15 @@ async def test_acknowledge_ping(self):
892892
async with asyncio_timeout(MS):
893893
await pong_waiter
894894

895+
async def test_acknowledge_canceled_ping(self):
896+
"""ping is acknowledged by a pong with the same payload after being canceled."""
897+
async with self.drop_frames_rcvd(): # drop automatic response to ping
898+
pong_waiter = await self.connection.ping("this")
899+
pong_waiter.cancel()
900+
await self.remote_connection.pong("this")
901+
with self.assertRaises(asyncio.CancelledError):
902+
await pong_waiter
903+
895904
async def test_acknowledge_ping_non_matching_pong(self):
896905
"""ping isn't acknowledged by a pong with a different payload."""
897906
async with self.drop_frames_rcvd(): # drop automatic response to ping
@@ -902,14 +911,26 @@ async def test_acknowledge_ping_non_matching_pong(self):
902911
await pong_waiter
903912

904913
async def test_acknowledge_previous_ping(self):
905-
"""ping is acknowledged by a pong with the same payload as a later ping."""
914+
"""ping is acknowledged by a pong for a later ping."""
906915
async with self.drop_frames_rcvd(): # drop automatic response to ping
907916
pong_waiter = await self.connection.ping("this")
908917
await self.connection.ping("that")
909918
await self.remote_connection.pong("that")
910919
async with asyncio_timeout(MS):
911920
await pong_waiter
912921

922+
async def test_acknowledge_previous_canceled_ping(self):
923+
"""ping is acknowledged by a pong for a later ping after being canceled."""
924+
async with self.drop_frames_rcvd(): # drop automatic response to ping
925+
pong_waiter = await self.connection.ping("this")
926+
pong_waiter_2 = await self.connection.ping("that")
927+
pong_waiter.cancel()
928+
await self.remote_connection.pong("that")
929+
async with asyncio_timeout(MS):
930+
await pong_waiter_2
931+
with self.assertRaises(asyncio.CancelledError):
932+
await pong_waiter
933+
913934
async def test_ping_duplicate_payload(self):
914935
"""ping rejects the same payload until receiving the pong."""
915936
async with self.drop_frames_rcvd(): # drop automatic response to ping

tests/sync/test_connection.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -678,7 +678,7 @@ def test_acknowledge_ping_non_matching_pong(self):
678678
self.assertFalse(pong_waiter.wait(MS))
679679

680680
def test_acknowledge_previous_ping(self):
681-
"""ping is acknowledged by a pong with the same payload as a later ping."""
681+
"""ping is acknowledged by a pong for as a later ping."""
682682
with self.drop_frames_rcvd(): # drop automatic response to ping
683683
pong_waiter = self.connection.ping("this")
684684
self.connection.ping("that")

0 commit comments

Comments
 (0)