| 173 | |
| 174 | |
| 175 | async def _shutdown_resources(): |
| 176 | logger = state.logger |
| 177 | logger.info("Shutting down resources...") |
| 178 | |
| 179 | # Signal global shutdown if event exists |
| 180 | try: |
| 181 | from config import GlobalState |
| 182 | |
| 183 | if hasattr(GlobalState, "IS_SHUTTING_DOWN") and hasattr( |
| 184 | GlobalState.IS_SHUTTING_DOWN, "set" |
| 185 | ): |
| 186 | GlobalState.IS_SHUTTING_DOWN.set() |
| 187 | except Exception as e: |
| 188 | logger.debug(f"Failed to set IS_SHUTTING_DOWN: {e}") |
| 189 | |
| 190 | state.should_exit = True |
| 191 | |
| 192 | if state.STREAM_PROCESS: |
| 193 | try: |
| 194 | state.STREAM_PROCESS.terminate() |
| 195 | state.STREAM_PROCESS.join(timeout=3) |
| 196 | if state.STREAM_PROCESS.is_alive(): |
| 197 | logger.warning("STREAM proxy did not terminate, killing...") |
| 198 | state.STREAM_PROCESS.kill() |
| 199 | state.STREAM_PROCESS.join(timeout=1) |
| 200 | except Exception as e: |
| 201 | logger.error(f"Error terminating STREAM proxy: {e}") |
| 202 | finally: |
| 203 | if state.STREAM_QUEUE: |
| 204 | try: |
| 205 | state.STREAM_QUEUE.close() |
| 206 | state.STREAM_QUEUE.join_thread() |
| 207 | except Exception: |
| 208 | pass |
| 209 | state.STREAM_PROCESS = None |
| 210 | state.STREAM_QUEUE = None |
| 211 | logger.info("STREAM proxy terminated.") |
| 212 | |
| 213 | if state.worker_task and not state.worker_task.done(): |
| 214 | logger.info("Cancelling worker task...") |
| 215 | state.worker_task.cancel() |
| 216 | try: |
| 217 | await asyncio.wait_for(state.worker_task, timeout=2.0) |
| 218 | logger.info("Worker task cancelled.") |
| 219 | except asyncio.TimeoutError: |
| 220 | logger.warning("Worker task did not respond to cancellation within 2s.") |
| 221 | except asyncio.CancelledError: |
| 222 | logger.debug("Worker task cancellation acknowledged (CancelledError).") |
| 223 | except Exception as e: |
| 224 | logger.error(f"Error cancelling worker task: {e}") |
| 225 | finally: |
| 226 | state.worker_task = None |
| 227 | |
| 228 | if state.page_instance: |
| 229 | try: |
| 230 | await _close_page_logic() |
| 231 | except asyncio.CancelledError: |
| 232 | logger.debug("Page closure cancelled (CancelledError).") |