B
    u9aG  ã               @   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Zddl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„ ƒZe eedƒd¡G dd	„ d	ejƒƒZe eedƒd¡G d
d„ deƒƒZe eedƒd¡G dd„ deƒƒZe eedƒd¡G dd„ deƒƒZe eedƒd¡e eedƒd¡G dd„ deƒƒƒZe eedƒd¡G dd„ deƒƒZG dd„ deƒZedkr€e ¡  dS )a±  
This test suite exercises some system calls subject to interruption with EINTR,
to check that it is actually handled transparently.
It is intended to be run by the main test suite within a child process, to
ensure there is no background thread running (so that signals are delivered to
the correct thread).
Signals are generated in-process using setitimer(ITIMER_REAL), which allows
sub-second periodicity (contrarily to signal()).
é    N)Úsupportc          	   c   s6   | ( y
| V  W n   |   ¡  ‚ Y nX W dQ R X dS )zGContext manager killing the subprocess if a Python exception is raised.N)Úkill)Úproc© r   ú"/usr/lib/python3.7/eintr_tester.pyÚkill_on_error   s    
r   Ú	setitimerzrequires setitimer()c               @   sH   e Zd ZdZdZdZdZdd„ Zdd„ Ze	dd	„ ƒZ
d
d„ Zdd„ ZdS )ÚEINTRBaseTestz Base class for EINTR tests. gš™™™™™¹?gš™™™™™É?c             C   s   |  j d7  _ d S )Né   )Úsignals)ÚselfÚsignumÚframer   r   r   Ú
sighandler1   s    zEINTRBaseTest.sighandlerc             C   sL   d| _ t tj| j¡| _t tj| j| j¡ t	t
dƒrHt
jddtjd d S )Nr   Údump_traceback_lateriX  T)ÚexitÚfile)r   ÚsignalÚSIGALRMr   Úorig_handlerr   ÚITIMER_REALÚsignal_delayÚsignal_periodÚhasattrÚfaulthandlerr   ÚsysÚ
__stderr__)r   r   r   r   ÚsetUp4   s    
zEINTRBaseTest.setUpc               C   s   t  t jdd¡ d S )Nr   )r   r   r   r   r   r   r   Ú
stop_alarm@   s    zEINTRBaseTest.stop_alarmc             C   s.   |   ¡  t tj| j¡ ttdƒr*t ¡  d S )NÚcancel_dump_traceback_later)r   r   r   r   r   r   r   )r   r   r   r   ÚtearDownD   s    
zEINTRBaseTest.tearDownc             O   s   t jdf| }tj|f|ŽS )Nz-c)r   Ú
executableÚ
subprocessÚPopen)r   ÚargsÚkwZcmd_argsr   r   r   r"   J   s    zEINTRBaseTest.subprocessN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   Ú
sleep_timer   r   Ústaticmethodr   r    r"   r   r   r   r   r	   %   s   r	   c               @   s|   e Zd ZdZdd„ Zdd„ Zdd„ Ze e	e
dƒd	¡d
d„ ƒZdd„ Zdd„ Ze e	e
dƒd¡dd„ ƒZdd„ Zdd„ ZdS )ÚOSEINTRTestz  EINTR tests for the os module. c             C   s   d| j  }|  |¡S )Nzimport time; time.sleep(%r))r*   r"   )r   Úcoder   r   r   Únew_sleep_processS   s    
zOSEINTRTest.new_sleep_processc                sL   d}‡ fdd„t |ƒD ƒ}xt |ƒD ]
}|ƒ  q$W x|D ]}| ¡  q8W d S )Né   c                s   g | ]}ˆ   ¡ ‘qS r   )r.   )Ú.0Ú_)r   r   r   ú
<listcomp>Y   s    z3OSEINTRTest._test_wait_multiple.<locals>.<listcomp>)ÚrangeÚwait)r   Ú	wait_funcZnumZ	processesr1   r   r   )r   r   Ú_test_wait_multipleW   s    

zOSEINTRTest._test_wait_multiplec             C   s   |   tj¡ d S )N)r6   Úosr4   )r   r   r   r   Ú	test_wait`   s    zOSEINTRTest.test_waitÚwait3zrequires wait3()c             C   s   |   dd„ ¡ d S )Nc               S   s
   t  d¡S )Nr   )r7   r9   r   r   r   r   Ú<lambda>e   ó    z(OSEINTRTest.test_wait3.<locals>.<lambda>)r6   )r   r   r   r   Ú
test_wait3c   s    zOSEINTRTest.test_wait3c             C   s   |   ¡ }||jƒ | ¡  d S )N)r.   Úpidr4   )r   r5   r   r   r   r   Ú_test_wait_singleg   s    
zOSEINTRTest._test_wait_singlec             C   s   |   dd„ ¡ d S )Nc             S   s   t  | d¡S )Nr   )r7   Úwaitpid)r=   r   r   r   r:   n   r;   z*OSEINTRTest.test_waitpid.<locals>.<lambda>)r>   )r   r   r   r   Útest_waitpidm   s    zOSEINTRTest.test_waitpidÚwait4zrequires wait4()c             C   s   |   dd„ ¡ d S )Nc             S   s   t  | d¡S )Nr   )r7   rA   )r=   r   r   r   r:   r   r;   z(OSEINTRTest.test_wait4.<locals>.<lambda>)r>   )r   r   r   r   Ú
test_wait4p   s    zOSEINTRTest.test_wait4c             C   sº   t  ¡ \}}|  t j|¡ dddg}d dddd| d	| j dd
dddf
¡}| j|t|ƒ|gd}t|ƒF t  |¡ x$|D ]}|  	|t  
|t|ƒ¡¡ q|W |  	| ¡ d¡ W d Q R X d S )Ns   hellos   worlds   spamÚ
zimport os, sys, timeÚ zwr = int(sys.argv[1])z
datas = %rzsleep_time = %rzfor data in datas:z$    # let the parent block on read()z    time.sleep(sleep_time)z    os.write(wr, data))Úpass_fdsr   )r7   ÚpipeÚ
addCleanupÚcloseÚjoinr*   r"   Ústrr   ÚassertEqualÚreadÚlenr4   )r   ÚrdÚwrÚdatasr-   r   Údatar   r   r   Ú	test_readt   s(    



zOSEINTRTest.test_readc             C   sÚ   t  ¡ \}}|  t j|¡ dtj }d dddd| j dtj ddd	d
ddddddddddf¡}| j|t	|ƒ|gd}t
|ƒR t  |¡ d}x,|t|ƒk rº|t  |t|ƒ|d … ¡7 }qW |  | ¡ d¡ W d Q R X d S )Nó   xrC   zimport io, os, sys, timerD   zrd = int(sys.argv[1])zsleep_time = %rzdata = b"x" * %szdata_len = len(data)z!# let the parent block on write()ztime.sleep(sleep_time)zread_data = io.BytesIO()z+while len(read_data.getvalue()) < data_len:z%    chunk = os.read(rd, 2 * data_len)z    read_data.write(chunk)zvalue = read_data.getvalue()zif value != data:z0    raise Exception("read error: %s vs %s bytes"z-                    % (len(value), data_len)))rE   r   )r7   rF   rG   rH   r   ZPIPE_MAX_SIZErI   r*   r"   rJ   r   rM   ÚwriteÚ
memoryviewrK   r4   )r   rN   rO   rQ   r-   r   Úwrittenr   r   r   Ú
test_write‘   s<    


 zOSEINTRTest.test_writeN)r&   r'   r(   r)   r.   r6   r8   ÚunittestÚ
skipUnlessr   r7   r<   r>   r@   rB   rR   rW   r   r   r   r   r,   O   s   	r,   c               @   sô   e Zd ZdZe eedƒd¡dd„ ƒZdd„ Z	e eejdƒd	¡d
d„ ƒZ
dd„ Zdd„ Zdd„ Ze eejdƒd¡dd„ ƒZdd„ Ze dd¡e eedƒd¡dd„ ƒƒZdd„ Ze ejd kd!¡d"d#„ ƒZd$d%„ Ze ejd kd!¡d&d'„ ƒZd(S ))ÚSocketEINTRTestz$ EINTR tests for the socket module. Ú
socketpairzneeds socketpair()c       	      C   sÜ   t  ¡ \}}|  |j¡ dddg}d ddddt|jƒ d	t|jƒ d
| d| j dddddddddf¡}| 	¡ }| j
|t|ƒ|gd}t|ƒB | ¡  x"|D ]}|  |||t|ƒƒ¡ q W |  | ¡ d¡ W d Q R X d S )NrS   ó   yó   zrC   zimport os, socket, sys, timerD   zfd = int(sys.argv[1])zfamily = %szsock_type = %sz
datas = %rzsleep_time = %rz)wr = socket.fromfd(fd, family, sock_type)zos.close(fd)zwith wr:z    for data in datas:z(        # let the parent block on recv()z        time.sleep(sleep_time)z        wr.sendall(data))rE   r   )Úsocketr[   rG   rH   rI   ÚintÚfamilyÚtyper*   Úfilenor"   rJ   r   rK   rM   r4   )	r   Z	recv_funcrN   rO   rP   r-   Úfdr   rQ   r   r   r   Ú
_test_recv¼   s6    


zSocketEINTRTest._test_recvc             C   s   |   tjj¡ d S )N)rd   r^   Zrecv)r   r   r   r   Ú	test_recvà   s    zSocketEINTRTest.test_recvÚrecvmsgzneeds recvmsg()c             C   s   |   dd„ ¡ d S )Nc             S   s   |   |¡d S )Nr   )rf   )ÚsockrQ   r   r   r   r:   å   r;   z.SocketEINTRTest.test_recvmsg.<locals>.<lambda>)rd   )r   r   r   r   Útest_recvmsgã   s    zSocketEINTRTest.test_recvmsgc       
      C   s  t  ¡ \}}|  |j¡ dtjd  }d ddddt|jƒ dt|j	ƒ d	| j
 d
tjd  dddddddddddddddddf¡}| ¡ }| j|t|ƒ|gd}t|ƒb | ¡  d}x>|t|ƒk rö||t|ƒ|d … ƒ}	||	d krît|ƒn|	7 }qºW |  | ¡ d¡ W d Q R X d S )Ns   xyzr/   rC   zimport os, socket, sys, timerD   zfd = int(sys.argv[1])zfamily = %szsock_type = %szsleep_time = %rzdata = b"xyz" * %szdata_len = len(data)z)rd = socket.fromfd(fd, family, sock_type)zos.close(fd)zwith rd:z$    # let the parent block on send()z    time.sleep(sleep_time)z'    received_data = bytearray(data_len)z	    n = 0z    while n < data_len:z8        n += rd.recv_into(memoryview(received_data)[n:])zif received_data != data:z0    raise Exception("recv error: %s vs %s bytes"z5                    % (len(received_data), data_len)))rE   r   )r^   r[   rG   rH   r   ZSOCK_MAX_SIZErI   r_   r`   ra   r*   rb   r"   rJ   r   rM   rU   rK   r4   )
r   Z	send_funcrN   rO   rQ   r-   rc   r   rV   Zsentr   r   r   Ú
_test_sendç   sJ    
zSocketEINTRTest._test_sendc             C   s   |   tjj¡ d S )N)ri   r^   Úsend)r   r   r   r   Ú	test_send  s    zSocketEINTRTest.test_sendc             C   s   |   tjj¡ d S )N)ri   r^   Zsendall)r   r   r   r   Útest_sendall  s    zSocketEINTRTest.test_sendallÚsendmsgzneeds sendmsg()c             C   s   |   dd„ ¡ d S )Nc             S   s   |   |g¡S )N)rm   )rg   rQ   r   r   r   r:     r;   z.SocketEINTRTest.test_sendmsg.<locals>.<lambda>)ri   )r   r   r   r   Útest_sendmsg  s    zSocketEINTRTest.test_sendmsgc             C   s´   t   t jt j¡}|  |j¡ | tjdf¡ | ¡ d }| 	¡  d 
dddtj d| d| j dd	d
ddf
¡}|  |¡}t|ƒ* | ¡ \}}| ¡  |  | ¡ d¡ W d Q R X d S )Nr   r
   rC   zimport socket, timerD   z	host = %rz	port = %szsleep_time = %rz# let parent block on accept()ztime.sleep(sleep_time)z,with socket.create_connection((host, port)):z    time.sleep(sleep_time))r^   ZAF_INETZSOCK_STREAMrG   rH   Zbindr   ZHOSTZgetsocknameZlistenrI   r*   r"   r   ZacceptrK   r4   )r   rg   Zportr-   r   Zclient_sockr1   r   r   r   Útest_accept  s*    

zSocketEINTRTest.test_accepté
   r/   Úmkfifozneeds mkfifo()c             C   s¾   t j}t  |¡ yt |¡ W n0 tk
rN } z|  d| ¡ W d d }~X Y nX |  t j|¡ d ddd| d| j	 dddd|f	¡}|  
|¡}t|ƒ ||ƒ |  | ¡ d	¡ W d Q R X d S )
Nzos.mkfifo(): %srC   zimport os, timerD   z	path = %azsleep_time = %rz# let the parent blockztime.sleep(sleep_time)r   )r   ÚTESTFNÚunlinkr7   rq   ÚPermissionErrorZskipTestrG   rI   r*   r"   r   rK   r4   )r   Zdo_open_close_readerZdo_open_close_writerÚfilenameÚer-   r   r   r   r   Ú
_test_open>  s*    
 

zSocketEINTRTest._test_openc             C   s   t |dƒ}| ¡  d S )NÚw)ÚopenrH   )r   ÚpathÚfpr   r   r   Úpython_open]  s    
zSocketEINTRTest.python_openÚdarwinz+hangs under macOS; see bpo-25234, bpo-35363c             C   s   |   d| j¡ d S )Nzfp = open(path, 'r')
fp.close())rw   r|   )r   r   r   r   Ú	test_opena  s    zSocketEINTRTest.test_openc             C   s   t  |t j¡}t  |¡ d S )N)r7   ry   ÚO_WRONLYrH   )r   rz   rc   r   r   r   Úos_openg  s    zSocketEINTRTest.os_openc             C   s   |   d| j¡ d S )Nz,fd = os.open(path, os.O_RDONLY)
os.close(fd))rw   r€   )r   r   r   r   Útest_os_openk  s    zSocketEINTRTest.test_os_openN)r&   r'   r(   r)   rX   rY   r   r^   rd   re   rh   ri   rk   rl   rn   ro   r   Zrequires_freebsd_versionr7   rw   r|   ÚskipIfr   Úplatformr~   r€   r   r   r   r   r   rZ   ¸   s"   $.
rZ   c               @   s   e Zd ZdZdd„ ZdS )ÚTimeEINTRTestz" EINTR tests for the time module. c             C   s:   t  ¡ }t  | j¡ |  ¡  t  ¡ | }|  || j¡ d S )N)ÚtimeÚ	monotonicÚsleepr*   r   ÚassertGreaterEqual)r   Út0Údtr   r   r   Ú
test_sleepv  s
    zTimeEINTRTest.test_sleepN)r&   r'   r(   r)   r‹   r   r   r   r   r„   r  s   r„   Úpthread_sigmaskzneed signal.pthread_sigmask()c               @   sL   e Zd ZdZdd„ Ze eedƒd¡dd„ ƒZ	e eedƒd¡d	d
„ ƒZ
dS )ÚSignalEINTRTestz$ EINTR tests for the signal module. c       
   	   C   sÌ   t j}t ¡ }t   |dd„ ¡}|  t j ||¡ d ddt ¡  dt|ƒ d| j dd	f¡}t  t j	|g¡}|  t jt j
|g¡ t ¡ }|  |¡}t|ƒ ||ƒ t ¡ | }	W d Q R X |  | ¡ d
¡ d S )Nc              W   s   d S )Nr   )r$   r   r   r   r:   Š  r;   z/SignalEINTRTest.check_sigwait.<locals>.<lambda>rC   zimport os, timezpid = %szsignum = %szsleep_time = %rztime.sleep(sleep_time)zos.kill(pid, signum)r   )r   ÚSIGUSR1r7   ÚgetpidrG   rI   r_   r*   rŒ   Ú	SIG_BLOCKÚSIG_UNBLOCKr…   r†   r"   r   rK   r4   )
r   r5   r   r=   Zold_handlerr-   Zold_maskr‰   r   rŠ   r   r   r   Úcheck_sigwait†  s&    



zSignalEINTRTest.check_sigwaitÚsigwaitinfozneed signal.sigwaitinfo()c             C   s   dd„ }|   |¡ d S )Nc             S   s   t  | g¡ d S )N)r   r“   )r   r   r   r   r5   ¤  s    z3SignalEINTRTest.test_sigwaitinfo.<locals>.wait_func)r’   )r   r5   r   r   r   Útest_sigwaitinfo¡  s    z SignalEINTRTest.test_sigwaitinfoÚsigtimedwaitc             C   s   dd„ }|   |¡ d S )Nc             S   s   t  | gd¡ d S )Ng      ^@)r   r•   )r   r   r   r   r5   ¬  s    z4SignalEINTRTest.test_sigtimedwait.<locals>.wait_func)r’   )r   r5   r   r   r   Útest_sigtimedwait©  s    z!SignalEINTRTest.test_sigtimedwaitN)r&   r'   r(   r)   r’   rX   rY   r   r   r”   r–   r   r   r   r   r   ~  s   r   c               @   s’   e Zd ZdZdd„ Ze ejdkd¡e 	e
edƒd¡dd	„ ƒƒZe 	e
ed
ƒd¡dd„ ƒZe 	e
edƒd¡dd„ ƒZe 	e
edƒd¡dd„ ƒZdS )ÚSelectEINTRTestz$ EINTR tests for the select module. c             C   s@   t  ¡ }t g g g | j¡ t  ¡ | }|  ¡  |  || j¡ d S )N)r…   r†   Úselectr*   r   rˆ   )r   r‰   rŠ   r   r   r   Útest_select¶  s
    zSelectEINTRTest.test_selectr}   z(poll may fail on macOS; see issue #28087Úpollzneed select.pollc             C   sF   t  ¡ }t ¡ }| | jd ¡ t ¡ | }|  ¡  |  || j¡ d S )Ng     @@)r˜   rš   r…   r†   r*   r   rˆ   )r   Úpollerr‰   rŠ   r   r   r   Ú	test_poll½  s    zSelectEINTRTest.test_pollÚepollzneed select.epollc             C   sN   t  ¡ }|  |j¡ t ¡ }| | j¡ t ¡ | }|  ¡  |  	|| j¡ d S )N)
r˜   r   rG   rH   r…   r†   rš   r*   r   rˆ   )r   r›   r‰   rŠ   r   r   r   Ú
test_epollÉ  s    zSelectEINTRTest.test_epollÚkqueuezneed select.kqueuec             C   sR   t  ¡ }|  |j¡ t ¡ }| d d| j¡ t ¡ | }|  ¡  |  	|| j¡ d S )Nr
   )
r˜   rŸ   rG   rH   r…   r†   Zcontrolr*   r   rˆ   )r   rŸ   r‰   rŠ   r   r   r   Útest_kqueueÔ  s    zSelectEINTRTest.test_kqueueÚdevpollzneed select.devpollc             C   sR   t  ¡ }|  |j¡ t ¡ }| | jd ¡ t ¡ | }|  ¡  |  	|| j¡ d S )Ng     @@)
r˜   r¡   rG   rH   r…   r†   rš   r*   r   rˆ   )r   r›   r‰   rŠ   r   r   r   Útest_devpollß  s    zSelectEINTRTest.test_devpollN)r&   r'   r(   r)   r™   rX   r‚   r   rƒ   rY   r   r˜   rœ   rž   r    r¢   r   r   r   r   r—   ²  s   
r—   c               @   s8   e Zd Zdd„ Ze e ¡ dkd¡dd„ ƒZdd„ Z	d	S )
ÚFNTLEINTRTestc          
   C   s  |   tjtj¡ d ddtj d| d| j f¡}t ¡ }|  |¡}t	|ƒ¾ t
tjdƒž}xht ¡ | }|dkr~td| ƒ‚y,||tjtjB ƒ ||tjƒ t d	¡ W q^ tk
rÀ   P Y q^X q^W ||tjƒ t ¡ | }|  || j¡ |  ¡  W d Q R X | ¡  W d Q R X d S )
NrC   zimport fcntl, timezwith open('%s', 'wb') as f:z   fcntl.%s(f, fcntl.LOCK_EX)z   time.sleep(%s)Úwbg      N@z failed to sync child in %.1f secg{®Gáz„?)rG   r   rs   rr   rI   r*   r…   r†   r"   r   ry   Ú	ExceptionÚfcntlZLOCK_EXZLOCK_NBZLOCK_UNr‡   ÚBlockingIOErrorrˆ   r   r4   )r   Z	lock_funcZ	lock_namer-   Z
start_timer   ÚfrŠ   r   r   r   Ú_lockì  s2    

zFNTLEINTRTest._lockZAIXzAIX returns PermissionErrorc             C   s   |   tjd¡ d S )NÚlockf)r©   r¦   rª   )r   r   r   r   Ú
test_lockf  s    zFNTLEINTRTest.test_lockfc             C   s   |   tjd¡ d S )NÚflock)r©   r¦   r¬   )r   r   r   r   Ú
test_flock  s    zFNTLEINTRTest.test_flockN)
r&   r'   r(   r©   rX   r‚   rƒ   Úsystemr«   r­   r   r   r   r   r£   ë  s    r£   Ú__main__)r)   Ú
contextlibr   r¦   r7   rƒ   r˜   r   r^   r"   r   r…   rX   Ztestr   Úcontextmanagerr   rY   r   ZTestCaser	   r,   rZ   r„   r   r—   r£   r&   Úmainr   r   r   r   Ú<module>	   s@   
)h :
/8)
