Close socket and transcode resources as needed
(self)
| 1598 | self.current_session = None |
| 1599 | |
| 1600 | def _close_socket(self): |
| 1601 | """Close socket and transcode resources as needed""" |
| 1602 | # First try to use _close_connection for HTTP resources |
| 1603 | if self.current_response or self.current_session: |
| 1604 | self._close_connection() |
| 1605 | |
| 1606 | # Stop HTTP reader thread if it exists |
| 1607 | if hasattr(self, 'http_reader') and self.http_reader: |
| 1608 | try: |
| 1609 | logger.debug(f"Stopping HTTP reader thread for channel {self.channel_id}") |
| 1610 | self.http_reader.stop() |
| 1611 | self.http_reader = None |
| 1612 | except Exception as e: |
| 1613 | logger.debug(f"Error stopping HTTP reader for channel {self.channel_id}: {e}") |
| 1614 | |
| 1615 | # Kill proc before closing self.socket. Closing relay_read while the stream |
| 1616 | # OS thread is blocked in select() on it does not reliably wake that select() |
| 1617 | # on Linux. Killing ffmpeg closes its relay_write, sending EOF to the stream |
| 1618 | # thread naturally. We close self.socket afterward as cleanup only. |
| 1619 | proc = self.transcode_process |
| 1620 | self.transcode_process = None # claim early so concurrent greenlets skip this block |
| 1621 | if proc: |
| 1622 | try: |
| 1623 | logger.debug(f"Killing transcode process for channel {self.channel_id}") |
| 1624 | proc.kill() |
| 1625 | |
| 1626 | # Give it a very short time to die |
| 1627 | try: |
| 1628 | proc.wait(timeout=0.5) |
| 1629 | except subprocess.TimeoutExpired: |
| 1630 | logger.error(f"Failed to kill transcode process even with force for channel {self.channel_id}") |
| 1631 | except Exception as e: |
| 1632 | logger.debug(f"Error terminating transcode process for channel {self.channel_id}: {e}") |
| 1633 | |
| 1634 | # Final attempt: try to kill directly |
| 1635 | try: |
| 1636 | proc.kill() |
| 1637 | except Exception as e: |
| 1638 | logger.error(f"Final kill attempt failed for channel {self.channel_id}: {e}") |
| 1639 | |
| 1640 | # Close relay socket after proc death; stream thread has already unblocked via EOF. |
| 1641 | if self.socket: |
| 1642 | try: |
| 1643 | self.socket.close() |
| 1644 | except Exception as e: |
| 1645 | logger.debug(f"Error closing socket for channel {self.channel_id}: {e}") |
| 1646 | |
| 1647 | if proc: |
| 1648 | # Explicitly close all subprocess pipes to prevent file descriptor leaks |
| 1649 | try: |
| 1650 | if proc.stdin: |
| 1651 | proc.stdin.close() |
| 1652 | if proc.stdout: |
| 1653 | proc.stdout.close() |
| 1654 | if proc.stderr: |
| 1655 | proc.stderr.close() |
| 1656 | logger.debug(f"Closed all subprocess pipes for channel {self.channel_id}") |
| 1657 | except Exception as e: |
no test coverage detected