Clean up resources on exit.
(self)
| 270 | return None |
| 271 | |
| 272 | def _cleanup(self): |
| 273 | """Clean up resources on exit.""" |
| 274 | try: |
| 275 | # Cancel all pending tasks |
| 276 | pending = asyncio.all_tasks(self.loop) |
| 277 | for task in pending: |
| 278 | task.cancel() |
| 279 | |
| 280 | # Run loop until all tasks are cancelled (with timeout on quick exit) |
| 281 | if pending: |
| 282 | gather = asyncio.gather(*pending, return_exceptions=True) |
| 283 | if self._quick_shutdown: |
| 284 | # Quick exit - don't wait long for tasks to cancel |
| 285 | try: |
| 286 | self.loop.run_until_complete( |
| 287 | asyncio.wait_for(gather, timeout=1.0) |
| 288 | ) |
| 289 | except asyncio.TimeoutError: |
| 290 | self.log.debug("Timeout waiting for tasks to cancel") |
| 291 | else: |
| 292 | self.loop.run_until_complete(gather) |
| 293 | |
| 294 | self.loop.close() |
| 295 | except Exception as e: |
| 296 | self.log.debug("Cleanup error: %s", e) |
| 297 | |
| 298 | # Close sockets |
| 299 | for s in self.sockets: |
| 300 | try: |
| 301 | s.close() |
| 302 | except Exception: |
| 303 | pass |