Commit cdd7b74
Distinguish drain-completed from first-caller-exited in pool.close sibling-signalling
``ConnectionPool.close()`` set ``_close_done`` unconditionally
in the finally so siblings parked on ``_close_done.wait()``
did not deadlock under cancel. But the same event is consumed
by the second-caller arm as "drain completed" — when an outer
cancel (``asyncio.timeout(pool.close())`` under SIGTERM-with-
budget) interrupted the first caller's ``_drain_idle``, the
second caller observed the event set and returned
"successfully" against a pool whose idle queue was still
non-empty.
Add a ``_drain_complete`` flag set after ``_drain_idle()``
returns normally (NOT in the finally). The second-caller arm
re-checks the flag after ``_close_done.wait()`` returns and
runs a best-effort
``asyncio.shield(_drain_remaining_after_cancel())``
sweep when the first caller bailed mid-drain — so the
documented "queue drained on close" promise is upheld even
when the first caller is interrupted.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent b69f8d4 commit cdd7b74
1 file changed
Lines changed: 26 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
279 | 279 | | |
280 | 280 | | |
281 | 281 | | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
282 | 292 | | |
283 | 293 | | |
284 | 294 | | |
| |||
1436 | 1446 | | |
1437 | 1447 | | |
1438 | 1448 | | |
| 1449 | + | |
| 1450 | + | |
| 1451 | + | |
| 1452 | + | |
| 1453 | + | |
| 1454 | + | |
| 1455 | + | |
| 1456 | + | |
| 1457 | + | |
| 1458 | + | |
| 1459 | + | |
1439 | 1460 | | |
1440 | 1461 | | |
1441 | 1462 | | |
| |||
1456 | 1477 | | |
1457 | 1478 | | |
1458 | 1479 | | |
| 1480 | + | |
| 1481 | + | |
| 1482 | + | |
| 1483 | + | |
| 1484 | + | |
1459 | 1485 | | |
1460 | 1486 | | |
1461 | 1487 | | |
| |||
0 commit comments