
    c#                     h   d Z dZddlZddlZddlmZmZmZmZ ddl	m	Z	m
Z
mZmZmZ ddlmZmZmZmZ ddlmZ ddlmZ  G d	 d
e      Zd ZdZdZdZdZdZdZ G d de      Z G d d      Z  G d de      Z! G d de!      Z" G d de!      Z# G d de!      Z$e!e%fZ& G d de      Z' G d  d!      Z(y)"zmodule providing:
* process information (linux specific: rely on /proc)
* a class for resource control (memory / time / cpu time)

This module doesn't work on windows platforms (only tested on linux)

:organization: Logilab



zrestructuredtext en    N)	getrlimit	setrlimit
RLIMIT_CPU	RLIMIT_AS)signalSIGXCPUSIGKILLSIGUSR2SIGUSR1)TimercurrentThreadThreadEvent)time)Nodec                       e Zd Zy)NoSuchProcessN)__name__
__module____qualname__     5/usr/lib/python3/dist-packages/logilab/common/proc.pyr   r   )   s    r   r   c                 \    t         j                  j                  d| z        s
t               y)zTcheck the a pid is registered in /proc
    raise NoSuchProcess exception if not
    z/proc/%sN)ospathexistsr   )pids    r   proc_existsr   -   s&     77>>*s*+o ,r                     c                   <    e Zd ZdZd Zd Zd Zd
dZd Zd Z	d Z
y	)ProcInfoz4provide access to process information found in /procc                     t        |      | _        t        j                  | | j                         t	        | j                         d| j                  z  | _        t        | j                         t                 | _        y )Nz/proc/%s/stat)	intr   r   __init__r   filestatusPPIDppid)selfr   s     r   r*   zProcInfo.__init__@   sR    s8dDHH%DHH#dhh.	d+,	r   c                 b    	 t        | j                         t                 S # t        $ r Y yw xY w)z,return the memory usage of the process in Kor   )r)   r,   VSIZEOSErrorr/   s    r   memory_usagezProcInfo.memory_usageG   s/    	t{{}U+,, 		s   " 	..c                     | j                         t        | j                  D cg c]  }|j                          c}      z   S c c}w N)r4   sumchildrenlineage_memory_usage)r/   childs     r   r9   zProcInfo.lineage_memory_usageN   s9      "STXTaTa)b5%*D*D*F)b%ccc)bs   A
c                     | j                         }t        |t                 t        |t                 z   }|r(|t        |t                 t        |t
                 z   z  }|S )zareturn the number of jiffies that this process has been scheduled
        in user and kernel mode)r,   r)   UTIMESTIMECUTIMECSTIME)r/   r8   r,   r   s       r   r   zProcInfo.timeQ   sT     6%=!Cu$66Cv'#fVn*===Dr   c                 d    t        | j                        j                         j                         S )z3return the list of fields found in /proc/<pid>/stat)openr+   readsplitr3   s    r   r,   zProcInfo.statusZ   s"    DII##%++--r   c                 F    | j                         d   j                  d      S )z1return the process name found in /proc/<pid>/stat   z())r,   stripr3   s    r   namezProcInfo.name^   s    {{}Q%%d++r   c                 b    t        j                  | j                        t        j                     S )zreturn the age of the process)r   statr+   ST_MTIMEr3   s    r   agezProcInfo.ageb   s    wwtyy!$--00r   N)r   )r   r   r   __doc__r*   r4   r9   r   r,   rG   rK   r   r   r   r'   r'   =   s)    >-d.,1r   r'   c                   (    e Zd ZdZd Zd Zd Zd Zy)ProcInfoLoaderzmanage process informationc                     i | _         y r6   )_loadedr3   s    r   r*   zProcInfoLoader.__init__j   s	    r   c              #   |   K   t        j                  d      D ]   }|j                         st        |       " yw)z%return a list of existent process idsz/procN)r   listdirisdigitr)   )r/   subdirs     r   	list_pidszProcInfoLoader.list_pidsm   s2     jj) 	"F~~&k!	"s   )<<c                     t        |      }	 | j                  |   S # t        $ r& t        |      }| |_        || j                  |<   |cY S w xY w)z%get a ProcInfo object for a given pid)r)   rP   KeyErrorr'   manager)r/   r   procinfos      r   loadzProcInfoLoader.loads   sR    #h	<<$$ 	}H#H (DLLO		s    ,A
Ac                     | j                         D ]X  }	 | j                  |      }|j                  8|j                  r,| j                  |j                        }|j	                  |       Z y# t
        $ r Y gw xY w)zload all processes informationN)rU   rZ   parentr.   appendr   )r/   r   rY   	pprocinfos       r   load_allzProcInfoLoader.load_all~   so    >># 	C99S>??*x}} $		(-- 8I$$X.	 ! s   AA--	A98A9N)r   r   r   rL   r*   rU   rZ   r_   r   r   r   rN   rN   g   s    $"		r   rN   c                       e Zd ZdZdZy)ResourceErrorz*Error raise when resource limit is reachedzUnknown Resource LimitNr   r   r   rL   limitr   r   r   ra   ra      s
    4$Er   ra   c                       e Zd ZdZdZy)	XCPUErrorz+Error raised when CPU Time limit is reachedzCPU TimeNrb   r   r   r   re   re      s
    5Er   re   c                       e Zd ZdZdZy)LineageMemoryErrorz\Error raised when the total amount of memory used by a process and
    it's child is reachedzLineage total MemoryNrb   r   r   r   rg   rg      s     #Er   rg   c                       e Zd ZdZdZy)TimeoutErrorz9Error raised when the process is running for to much timez	Real TimeNrb   r   r   r   ri   ri      s
    CEr   ri   c                   $    e Zd ZdZddZd Zd Zy)MemorySentinelz\A class checking a process don't use too much memory in a separated
    daemonic thread
    Nc                     t        j                  | | j                  d       || _        t	               | _        || _        | j                  d       ||| _
        y t        j                         | _
        y )NzTest.Sentinel)targetrG   T)r   r*   _runmemory_limitr   _stopinterval	setDaemonr   getpidgpid)r/   rq   ro   rt   s       r   r*   zMemorySentinel.__init__   sR    TYY_E(W
 t ,D	"))+	r   c                 8    | j                   j                          y)zstop apN)rp   setr3   s    r   stopzMemorySentinel.stop   s    

r   c                    t               }| j                  j                         s| j                  |j	                  | j
                        j                         k  r$t        j                  | j
                  t               | j                  j                  | j                         | j                  j                         sy y r6   )rN   rp   isSetro   rZ   rt   r9   r   killpgr   waitrq   )r/   pils     r   rn   zMemorySentinel._run   sv    **""$  CHHTYY$7$L$L$NN		$))W-JJOODMM* **""$r   r6   )r   r   r   rL   r*   rw   rn   r   r   r   rk   rk      s    >+r   rk   c                   8    e Zd Zd	dZd Zd Zd Zd Zd Zd Z	y)
ResourceControllerNc                     t         dk(  rt        d      || _        || _        || _        || _        d | _        d | _        d | _        d | _	        d | _
        d | _        d | _        d| _        d| _        d | _        d| _        y )NzUnsupported platformr   )r   RuntimeErrormax_time
max_memorymax_cpu_time	_reprieve_timer
_msentinel_old_max_memory_old_usr1_hdlr_old_max_cpu_time_old_usr2_hdlr_old_sigxcpu_hdlr
_limit_set
_abort_try_start_time_elapse_time)r/   r   r   r   max_reprieves        r   r*   zResourceController.__init__   s    b=566 $(%#"!%"!%r   c                     t               r6   )ri   r/   sigframes      r   _hangle_sig_timeoutz&ResourceController._hangle_sig_timeout   s
    nr   c                     | j                   | j                  k  r | xj                   dz  c_         t        d      t        j                  t        j
                         t               y )NrE   zMemory limit reached)r   r   rg   r   rz   rs   r	   r   s      r   _hangle_sig_memoryz%ResourceController._hangle_sig_memory   s@    ??T^^+OOq O$%;<<IIbiik7+r   c                     | j                   | j                  k  r | xj                   dz  c_         t        d      t        j                  t        j
                         t               y )NrE   zSoft CPU time limit reached)r   r   re   r   rz   rs   r	   r   s      r   _handle_sigxcpuz"ResourceController._handle_sigxcpu   s@    ??T^^+OOq O9::IIbiik7+r   c                    | j                   | j                  k  r| xj                   dz  c_         t        j                  t        j                         t
               | j                  dkD  r6t        d| j                        | _	        | j                  j                          y y t        j                  t        j                         t               y )NrE   r   )r   r   r   rz   rs   r
   r   r   	_time_outr   startr	   r3   s    r   r   zResourceController._time_out   s}    ??T^^+OOq OIIbiik7+"#At~~6!!# # IIbiik7+r   c                 <   t               j                         dk(  sJ t        j                          | j                  dk  r| j
                  t        t        | j                        | _	        t        t        dt        | j
                        | j                  z
        | j                        | _        t        t!                     | _        | j                  j%                          | j&                  gt)        t*              | _        t        | j&                        | j,                  d   f}t        t.        | j0                        | _        t5        t*        |       | j6                  t9        dt        | j6                              | _        t)        t<              | _        t        t@        | jB                        | _"        t        | j6                        | j>                  d   f}t5        t<        |       | j:                  j%                          | xj                  dz  c_        y)zset up the process limit
MainThreadr   NrE   )#r   getNamer   setpgrpr   r   r   r
   r   r   r   maxr)   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rk   r   r   r   r   r   r   )r/   	cpu_limitas_limits      r   setup_limitzResourceController.setup_limit   s~   &&(L888


??a}}(&,Wd6N6N&O##C3t}}+=@Q@Q+Q$RTXTbTbc#&tv; !!#  ,)2:)>& !2!23T5K5KA5NO	)/9M9M)N&*i0*"0C4H"I'0';$&,Wd6M6M&N#0$2F2Fq2IJ)X.%%'1r   c                    | j                   dkD  r| j                  n| j                  j                          | xj                  t        t                     | j                  z
  z  c_        d| _        t        t        | j                         | j                  4t        t        | j                         t        t        | j                          | j"                  U| j$                  j'                          d| _        t        t(        | j*                         t        t,        | j.                         | xj                   dz  c_         y)zreinstall the old process limitr   NrE   )r   r   r   cancelr   r)   r   r   r   r
   r   r   r   r   r   r   r   r   r   rw   r   r   r   r   r3   s    r   clean_limitzResourceController.clean_limit  s    ??Q}}(""$!!S[43C3C%CC!"w 3 34  ,*d&<&<=w 6 67*$$&"&)T%9%9:w 3 341r   )NNN<   )
r   r   r   r*   r   r   r   r   r   r   r   r   r   r~   r~      s%    &,,,0r   r~   ))rL   __docformat__r   rI   resourcer   r   r   r   r   r   r	   r
   r   	threadingr   r   r   r   r   logilab.common.treer   	Exceptionr   r   r-   r<   r=   r>   r?   r1   r'   rN   ra   re   rg   ri   MemoryErrorRESOURCE_LIMIT_EXCEPTIONrk   r~   r   r   r   <module>r      s   $
 & 	  @ @ = = 9 9  $	I 	 	

		
'1t '1T   F%I % # #=  *;7 +V +2W Wr   