
    `gjd                        d Z ddlmZ ddlZddlZ	 ddlZdZ	 ddl	Z
dZddlZdZd	dZ	 	 	 	 	 	 d
dZy# e$ r dZdZY 'w xY w# e$ r dZ
dZY /w xY w)uG  Shared spurious stdin-EOF recovery for the TUI gateway entry point and slash worker.

When a child process inherits fd 0 (stdin) and sets ``O_NONBLOCK``, the flag
lands on the **shared open file description** — not just the child's descriptor.
The gateway's next ``read()`` returns ``EAGAIN``, which CPython's buffered
``TextIOWrapper`` converts to ``b''`` (apparent EOF), killing the gateway.

This module provides:
- :func:`diagnose_stdin_state` — forensic diagnostic (``O_NONBLOCK`` / ``SO_RCVTIMEO``)
- :func:`handle_spurious_eof` — check whether an empty ``readline()`` is a genuine
  peer-close or a spurious EOF, and recover if spurious.

The recovery is **POSIX-only** (``fcntl``).  On Windows, ``O_NONBLOCK`` on a
shared file description is not a concern, so the guard simply reports a
genuine EOF and lets the caller exit.
    )annotationsNTF
   c                    g } t         rUt        O	 t        j                  dt        j                        }| j	                  d|t
        j                  z  rdnd        n| j	                  d       t        rt        	 t        j                  dt        j                  t        j                        }	 |j                  t        j                  t        j                        }| j	                  d|       |j!                          	 | rd	j#                  |       S d
S # t        $ r}| j	                  d|        Y d}~d}~ww xY w# |j!                          w xY w# t        $ r Y _w xY w)a  Return a diagnostic string about stdin's current state.

    Used for crash-log forensics when stdin iteration falls through.
    Distinguishes genuine peer-close (flag clear) from spurious EOF
    caused by a child setting ``O_NONBLOCK`` on the shared file description.
    Nr   zO_NONBLOCK=10zF_GETFL error: zO_NONBLOCK=n/a (no fcntl)zSO_RCVTIMEO=z, unknown)
_HAS_FCNTL_fcntlfcntlF_GETFLappendos
O_NONBLOCK	Exception_HAS_SOCKET_socketfromfdAF_UNIXSOCK_STREAM
getsockopt
SOL_SOCKETSO_RCVTIMEOclosejoin)partsflagsestvs        N/root/.hermes/venv/lib/python3.12/site-packages/tui_gateway/_stdin_recovery.pydiagnose_stdin_stater!   0   s!    Ef(	0LLFNN3ELL;ebmm.Cs&MNO 	01
 w*
	q'//73F3FGA\\'"4"4g6I6IJ|B623 	  %499U3)3)  	0LL?1#.//	0" 	 		sC   AD <3E 0AE 2E 	D?!D::D?EE 	E#"E#c           	        t         rt        	 |d       y	 t        j                  dt        j                        }t	        |t
        j                  z        }|s	 |d       yt        j                         }| j                  |       | D cg c]  }||dz
  kD  s| c}| dd t        |       t        kD  r |dt        |        dt         d       yt               } |d	|        t        j                  dd
       t        rt        	 t        j                   dt        j"                  t        j$                        }	 |j'                  t        j(                  t        j*                  t-        j.                  ddd             |j1                          y
y
# t        $ r d}Y Kw xY wc c}w # |j1                          w xY w# t        $ r Y y
w xY w)u  Check whether an empty ``readline()`` is spurious; recover if so.

    Returns ``True`` if the caller should ``continue`` the read loop
    (spurious EOF was recovered), ``False`` if it should ``break`` (genuine
    peer-close or rate limit exceeded).

    ``log_fn`` is called with a diagnostic string — ``_log_exit`` in
    ``entry.py``, ``print(file=sys.stderr)`` in ``slash_worker.py``.
    Nzstdin EOF (peer closed)Fr   <   z+stdin spurious-EOF recovery rate exceeded (z
/min, cap )z=stdin spurious EOF (subprocess O_NONBLOCK flip), recovering: Tll)r	   r
   r   r   boolr   r   r   timer   lenMAX_RECOVERIES_PER_MINUTEr!   set_blockingr   r   r   r   r   
setsockoptr   r   structpackr   )recovery_timeslog_fnr   is_nonblocknowtdiagr   s           r    handle_spurious_eofr4   S   s     6-()Q/52==01 ()
 ))+C#$2Cqa#(lCN1
>66N#$J/H.IL	
 !D
J4&QR OOAt w*	q'//73F3FGAW//1D1DfkkRVXY[\F]^	 [   D2 	 	
 	sI   A F F&F&
3G  >AF+ G  F#"F#+F==G   	GG)returnstr)r.   zlist[float]r/   objectr5   r&   )__doc__
__future__r   r   r'   r   r
   r	   ImportErrorsocketr   r   r,   r)   r!   r4        r    <module>r>      s   " # 	 J
K
    4FDDD 
Ds  FJ  GKs   4 A 	A A 	AA