Fetch data from socket with timeout handling
(self)
| 1694 | self._buffer_check_timers = [] |
| 1695 | |
| 1696 | def fetch_chunk(self): |
| 1697 | """Fetch data from socket with timeout handling""" |
| 1698 | if not self.connected or not self.socket: |
| 1699 | return False |
| 1700 | |
| 1701 | try: |
| 1702 | # Set timeout for chunk reads |
| 1703 | chunk_timeout = ConfigHelper.chunk_timeout() # Use centralized timeout configuration |
| 1704 | |
| 1705 | try: |
| 1706 | # Handle different socket types with timeout |
| 1707 | if hasattr(self.socket, 'recv'): |
| 1708 | # Standard socket - set timeout |
| 1709 | original_timeout = self.socket.gettimeout() |
| 1710 | self.socket.settimeout(chunk_timeout) |
| 1711 | chunk = self.socket.recv(Config.CHUNK_SIZE) |
| 1712 | self.socket.settimeout(original_timeout) # Restore original timeout |
| 1713 | else: |
| 1714 | # Non-socket file object (io.FileIO from os.fdopen) - use raw |
| 1715 | # fd + os.read to stay cooperative under gevent. |
| 1716 | import select as _select |
| 1717 | import os as _os |
| 1718 | |
| 1719 | try: |
| 1720 | fd = self.socket.fileno() |
| 1721 | except (ValueError, OSError): |
| 1722 | self.connected = False |
| 1723 | return False |
| 1724 | |
| 1725 | try: |
| 1726 | ready, _, _ = _select.select([fd], [], [], chunk_timeout) |
| 1727 | except (ValueError, OSError): |
| 1728 | self.connected = False |
| 1729 | return False |
| 1730 | |
| 1731 | if not ready: |
| 1732 | logger.debug(f"Chunk read timeout ({chunk_timeout}s) for channel {self.channel_id}") |
| 1733 | return False |
| 1734 | |
| 1735 | try: |
| 1736 | chunk = _os.read(fd, Config.CHUNK_SIZE) |
| 1737 | except OSError as e: |
| 1738 | import errno as _errno |
| 1739 | if e.errno == _errno.EAGAIN and (self.stop_requested or not self.running): |
| 1740 | self.connected = False |
| 1741 | return False |
| 1742 | logger.warning(f"Read error for channel {self.channel_id}: {e}") |
| 1743 | self.connected = False |
| 1744 | return False |
| 1745 | |
| 1746 | except socket.timeout: |
| 1747 | # Socket timeout occurred |
| 1748 | logger.debug(f"Socket timeout ({chunk_timeout}s) for channel {self.channel_id}") |
| 1749 | return False |
| 1750 | |
| 1751 | if not chunk: |
| 1752 | # Connection closed by server |
| 1753 | logger.warning(f"Server closed connection for channel {self.channel_id}") |
no test coverage detected