(self)
| 213 | self.assertTrue(task.done()) |
| 214 | |
| 215 | async def test_abort_clients(self): |
| 216 | async def serve(rd, wr): |
| 217 | fut.set_result((rd, wr)) |
| 218 | await wr.wait_closed() |
| 219 | |
| 220 | fut = asyncio.Future() |
| 221 | srv = await asyncio.start_server(serve, socket_helper.HOSTv4, 0) |
| 222 | self.addCleanup(srv.close) |
| 223 | |
| 224 | addr = srv.sockets[0].getsockname() |
| 225 | (c_rd, c_wr) = await asyncio.open_connection(addr[0], addr[1], limit=4096) |
| 226 | self.addCleanup(c_wr.close) |
| 227 | |
| 228 | (s_rd, s_wr) = await fut |
| 229 | |
| 230 | # Limit the socket buffers so we can more reliably overfill them |
| 231 | s_sock = s_wr.get_extra_info('socket') |
| 232 | s_sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 65536) |
| 233 | c_sock = c_wr.get_extra_info('socket') |
| 234 | c_sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 65536) |
| 235 | |
| 236 | # Get the reader in to a paused state by sending more than twice |
| 237 | # the configured limit |
| 238 | s_wr.write(b'a' * 4096) |
| 239 | s_wr.write(b'a' * 4096) |
| 240 | s_wr.write(b'a' * 4096) |
| 241 | while c_wr.transport.is_reading(): |
| 242 | await asyncio.sleep(0) |
| 243 | |
| 244 | # Get the writer in a waiting state by sending data until the |
| 245 | # kernel stops accepting more data in the send buffer. |
| 246 | # gh-122136: getsockopt() does not reliably report the buffer size |
| 247 | # available for message content. |
| 248 | # We loop until we start filling up the asyncio buffer. |
| 249 | # To avoid an infinite loop we cap at 10 times the expected value |
| 250 | c_bufsize = c_sock.getsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF) |
| 251 | s_bufsize = s_sock.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF) |
| 252 | for i in range(10): |
| 253 | s_wr.write(b'a' * c_bufsize) |
| 254 | s_wr.write(b'a' * s_bufsize) |
| 255 | if s_wr.transport.get_write_buffer_size() > 0: |
| 256 | break |
| 257 | self.assertNotEqual(s_wr.transport.get_write_buffer_size(), 0) |
| 258 | |
| 259 | task = asyncio.create_task(srv.wait_closed()) |
| 260 | await asyncio.sleep(0) |
| 261 | self.assertFalse(task.done()) |
| 262 | |
| 263 | srv.close() |
| 264 | srv.abort_clients() |
| 265 | await asyncio.sleep(0) |
| 266 | await asyncio.sleep(0) |
| 267 | self.assertTrue(task.done()) |
| 268 | |
| 269 | async def test_close_with_hanging_client(self): |
| 270 | # Synchronize server cancellation only after the socket connection is |
nothing calls this directly
no test coverage detected