Skip to content

Commit 8a8f749

Browse files
committed
gh-135444: fix DatagramTransport buffer_size accounting
Commit 73e8637 added 8 to the buffer_size when send could not be called right away. However, it did not complete this accounting by removing 8 from the buffer size when sending did finally complete.
1 parent f273fd7 commit 8a8f749

File tree

4 files changed

+46
-3
lines changed

4 files changed

+46
-3
lines changed

Lib/asyncio/proactor_events.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,7 @@ def _loop_writing(self, fut=None):
526526
return
527527

528528
data, addr = self._buffer.popleft()
529-
self._buffer_size -= len(data)
529+
self._buffer_size -= len(data) + 8 # include header bytes
530530
if self._address is not None:
531531
self._write_fut = self._loop._proactor.send(self._sock,
532532
data)

Lib/asyncio/selector_events.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1291,15 +1291,15 @@ def sendto(self, data, addr=None):
12911291
def _sendto_ready(self):
12921292
while self._buffer:
12931293
data, addr = self._buffer.popleft()
1294-
self._buffer_size -= len(data)
1294+
self._buffer_size -= len(data) + 8 # include header bytes
12951295
try:
12961296
if self._extra['peername']:
12971297
self._sock.send(data)
12981298
else:
12991299
self._sock.sendto(data, addr)
13001300
except (BlockingIOError, InterruptedError):
13011301
self._buffer.appendleft((data, addr)) # Try again later.
1302-
self._buffer_size += len(data)
1302+
self._buffer_size += len(data) + 8 # include header bytes
13031303
break
13041304
except OSError as exc:
13051305
self._protocol.error_received(exc)

Lib/test/test_asyncio/test_proactor_events.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,8 @@ def test_sendto(self):
566566
self.assertTrue(self.proactor.sendto.called)
567567
self.proactor.sendto.assert_called_with(
568568
self.sock, data, addr=('0.0.0.0', 1234))
569+
self.assertFalse(transport._buffer)
570+
self.assertEqual(0, transport._buffer_size)
569571

570572
def test_sendto_bytearray(self):
571573
data = bytearray(b'data')

Lib/test/test_asyncio/test_selector_events.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,6 +1497,47 @@ def test_sendto_closing(self):
14971497
transport.sendto(b'data', (1,))
14981498
self.assertEqual(transport._conn_lost, 2)
14991499

1500+
def test_sendto_sendto_ready(self):
1501+
data = b'data'
1502+
1503+
# First queue up a buffer by having the socket block
1504+
self.sock.sendto.side_effect = BlockingIOError
1505+
transport = self.datagram_transport()
1506+
transport.sendto(data, ('0.0.0.0', 12345))
1507+
self.loop.assert_writer(7, transport._sendto_ready)
1508+
self.assertEqual(1, len(transport._buffer))
1509+
self.assertEqual(transport._buffer_size, len(data) + 8)
1510+
1511+
# Now let the socket send the buffer
1512+
self.sock.sendto.side_effect = None
1513+
transport._sendto_ready()
1514+
self.assertTrue(self.sock.sendto.called)
1515+
self.assertEqual(
1516+
self.sock.sendto.call_args[0], (data, ('0.0.0.0', 12345)))
1517+
self.assertFalse(self.loop.writers)
1518+
self.assertFalse(transport._buffer)
1519+
self.assertEqual(transport._buffer_size, 0)
1520+
1521+
def test_sendto_sendto_ready_blocked(self):
1522+
data = b'data'
1523+
1524+
# First queue up a buffer by having the socket block
1525+
self.sock.sendto.side_effect = BlockingIOError
1526+
transport = self.datagram_transport()
1527+
transport.sendto(data, ('0.0.0.0', 12345))
1528+
self.loop.assert_writer(7, transport._sendto_ready)
1529+
self.assertEqual(1, len(transport._buffer))
1530+
self.assertEqual(transport._buffer_size, len(data) + 8)
1531+
1532+
# Now try to send the buffer and let it get requeued
1533+
transport._sendto_ready()
1534+
self.assertTrue(self.sock.sendto.called)
1535+
self.assertEqual(
1536+
self.sock.sendto.call_args[0], (data, ('0.0.0.0', 12345)))
1537+
self.assertTrue(self.loop.writers)
1538+
self.assertEqual(1, len(transport._buffer))
1539+
self.assertEqual(transport._buffer_size, len(data) + 8)
1540+
15001541
def test_sendto_ready(self):
15011542
data = b'data'
15021543
self.sock.sendto.return_value = len(data)

0 commit comments

Comments
 (0)