a
    è»jJ!  ã                   @   s¸   d Z ddlZddlZddlZddlZddlZddlmZ ej 	dd¡ ddl
ZddlZedƒZed Zed d ZejZd	Zd	Zd
d„ Zdd„ Zdd„ Zdd„ Zedkr´e eƒ ¡ dS )a6  Restart the live maker safely. Use this instead of doing it by hand.

WHY THIS EXISTS. Restarting by hand meant: write the kill file, sleep a fixed
30s, delete the lock file, launch. That deletes the single-instance lock -- the
one guard built specifically to stop two makers running -- and on 2026-08-17 the
old process had not finished exiting when the new one started. Two makers ran
against the same account, every leg went to two resting orders, and 26
duplicates accumulated before it was caught. Same failure as 2026-08-16, caused
by the fix for it being switched off by the procedure meant to use it.

The lock is never touched here. A cleanly exiting maker releases it itself, and
if it dies without doing so the heartbeat expires on its own.

    python main\restart_maker.py -- --live --books 80 --minutes 1440
é    N)ÚPathzE:\soccer\mainz	E:\soccerZ
STOP_MAKERZresearchz.mm_maker_live.lockéx   c                  C   s4   t jg d¢dddd�} dd„ | j ¡ D ƒ}|p2tƒ S )z=PIDs of live maker processes, via WMI (no psutil dependency).)Z
powershellz
-NoProfilez-Commandz›Get-CimInstance Win32_Process -Filter "Name like '%python%'" | Where-Object { $_.CommandLine -match 'mm_maker_live\.py' } | ForEach-Object { $_.ProcessId }Té<   )Úcapture_outputÚtextZtimeoutc                 S   s    g | ]}|  ¡  ¡ rt|ƒ‘qS © )ÚstripÚisdigitÚint)Ú.0Úxr   r   úrestart_maker.pyÚ
<listcomp>0   ó    zrunning.<locals>.<listcomp>)Ú
subprocessÚrunÚstdoutÚsplitÚ_lock_holder)ÚoutÚpidsr   r   r   Úrunning#   s    	ör   c                 C   s^   zDddl }|jj}| ddt| ƒ¡}|r8| |¡ W dS | ¡ dkW S  tyX   Y dS 0 dS )aP  Alive check that does not lie about processes owned by SYSTEM.

    Deliberately duplicated from mm_maker_live rather than imported: the tool
    that restarts the maker must not depend on importing the maker.
    ERROR_ACCESS_DENIED (5) means it exists and is not ours; 87 means no such
    pid; anything else fails safe to alive.
    r   Ni   FTéW   )ÚctypesZwindllZkernel32ZOpenProcessr
   ZCloseHandleZGetLastErrorÚ	Exception)Úpidr   ÚkÚhr   r   r   Ú
_pid_alive4   s    
r   c               
   C   s’   zt  tjdd�¡} W n tttfy2   g  Y S 0 |  d¡}t ¡ t	|  d¡pRdƒ }|rŽ|t
k rŽt|ƒrŽtd|› d|d›d	�ƒ t|ƒgS g S )
a   PID from the lock file, when its heartbeat is fresh and the pid lives.

    WMI IS NOT ENOUGH. Win32_Process.CommandLine comes back EMPTY for a process
    owned by another user unless this shell is elevated, and the maker normally
    runs as SYSTEM under the guard. So running() matched nothing, printed "no
    maker running", and this script launched a second maker alongside a healthy
    one -- observed 2026-08-29. The lock file is written by the maker itself and
    is readable whoever owns the process, so it sees what WMI hides.
    úutf-8©Úencodingr   Z	heartbeatr   z&  lock file reports a live maker (pid z, heartbeat z.0fzs ago) that WMI could not see)ÚjsonÚloadsÚLOCKÚ	read_textÚOSErrorÚ
ValueErrorÚ	TypeErrorÚgetÚtimeÚfloatÚLOCK_STALE_Sr   Úprintr
   )Údr   Zager   r   r   r   H   s    



ÿ

r   c               
      s  t jdd … } | r*| d dkr*| dd … } tƒ }|rÖtdt|ƒ› d|› �ƒ tjddd� t ¡ t }t ¡ |k rŠtƒ }|s~qÌt 	d	¡ qftd
t› d|› �ƒ |D ]}t
jdddt|ƒgdd� q¢t 	d	¡ tdƒ ntdƒ dd„ }zÖt d¡ tjddd�}t d¡ t ¡ �ptƒ ‰ d  }‰tdƒD ]\}t 	d¡ t ¡ �pDi  dg ¡�pRg }‡ fdd„|D ƒ‰‡fdd„|D ƒ}|�s* �qˆ�q*ˆ�rºtdtˆƒ› d�d td d!„ ˆD ƒƒ¡ ƒ W nP t�y }	 z6td"t|	ƒj› d#|	› �ƒ td$ƒ |ƒ  W Y d }	~	dS d }	~	0 0 td%|› d&|d u�r*t|ƒnd'› �ƒ |�rLtd(ƒ |ƒ  dS |ƒ  t ¡ �rztd)tjdd�› �ƒ td*ƒ td+ttd, d- ƒg|  }
td.d/ |
dd … ¡ƒ td0 d1 }|j d2dd��(}t
j!|
ttƒ|t
j"d3� W d   ƒ n1 �sö0    Y  t 	d4¡ td5tƒ ƒ dS )6Né   r   z--z	stopping z maker process(es): Zrestartr   r    é   z  did NOT exit within zs -- force killing Ztaskkillz/Fz/PIDT)r   z  all maker processes gonezno maker runningc               
   S   sZ   zt  ¡ rt  ¡  W n@ tyT }  z(tdt › d| › �ƒ tdƒ W Y d } ~ n
d } ~ 0 0 d S )Nz  WARNING: could not remove ú: z=  THE MAKER WILL NOT START until that file is deleted by hand)ÚKILLÚexistsÚunlinkr   r-   )Úer   r   r   Ú_release_killŽ   s    zmain.<locals>._release_kill)Z	keep_heldFé   é   Zordersc                    s0   g | ](}t | d d¡ƒ dd¡d ˆ v r|‘qS )ÚtickerÚ ú-r/   r   )Ústrr)   Úrsplit©r   Úo)Ú_heldr   r   r   ¢   s    ÿzmain.<locals>.<listcomp>c                    s   g | ]}|ˆ vr|‘qS r   r   r>   )Úkeptr   r   r   ¤   r   zkept z* completing leg(s) of held books resting: z, c                 s   s   | ]}|  d d¡V  qdS )r9   r:   N)r)   r>   r   r   r   Ú	<genexpr>©   r   zmain.<locals>.<genexpr>zcancel/verify FAILED: r1   zJREFUSING to start this cycle; releasing the kill file so the guard retriesz
cancelled z; resting now ú?z'REFUSING to start: orders still restingz  note: lock file present -- z=  leaving it alone; the new process will refuse if it is livez-uÚmainzmm_maker_live.pyz	starting:ú Zlogszmm_restart.logÚa)Úcwdr   Ústderré   zrunning pids:)#ÚsysÚargvr   r-   Úlenr2   Z
write_textr*   ÚWAIT_EXIT_SÚsleepr   r   r<   ÚkmZset_liveZ
cancel_allZheld_eventsÚsetÚrangeÚktZget_open_ordersr)   ÚjoinÚsortedr   ÚtypeÚ__name__r$   r3   r%   ÚPYÚROOTÚopenÚPopenZSTDOUT)Úargsr   ZdeadlineÚpr6   ÚnÚleftÚ_Z_allr5   ÚcmdÚlogZfhr   )r@   rA   r   rD   _   sz    ÿ





ÿ
&
8
rD   Ú__main__)Ú__doc__r"   Úosr   rJ   r*   Úpathlibr   ÚpathÚinsertZkalshi_traderrR   Zkalshi_makerrO   rX   r2   r$   Ú
executablerW   rM   r,   r   r   r   rD   rV   Úexitr   r   r   r   Ú<module>   s*   j