
    6bhF                     .   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ZddlmZ ddlmZ ddlmZ dZej(                  d        Z ej,                   eed      d	       G d
 dej0                               Z ej,                   eed      d	       G d de             Z ej,                   eed      d	       G d de             Z ej,                   eed      d	       G d de             Z ej,                   eed      d	       ej,                   eed      d       G d de                    Z ej,                   eed      d	       G d de             Z G d de      Ze dk(  r ejB                          yy)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)support)	os_helper)socket_helperg{Gz?c              #   r   K   | 5  	 |  	 ddd       y#  | j                           xY w# 1 sw Y   yxY ww)zGContext manager killing the subprocess if a Python exception is raised.N)kill)procs    :/opt/python-3.12.12/usr/lib/python3.12/test/_test_eintr.pykill_on_errorr
   #   s6      
	J 
	IIK 
s    7+	7(+47	setitimerzrequires setitimer()c                   J    e Zd ZdZdZdZdZd Zd Ze	d        Z
d Zd Zd	 Zy
)EINTRBaseTestz Base class for EINTR tests. g?g?c                 .    | xj                   dz  c_         y N   )signals)selfsignumframes      r	   
sighandlerzEINTRBaseTest.sighandler:   s        c                 6   d| _         t        j                  t        j                  | j                        | _        t        j
                  t        j                  | j                  | j                         t        j                  ddt        j                         y )Nr   iX  T)exitfile)r   signalSIGALRMr   orig_handlerr   ITIMER_REALsignal_delaysignal_periodfaulthandlerdump_traceback_latersys
__stderr__r   s    r	   setUpzEINTRBaseTest.setUp=   sf    "MM&..$//J++T->->++	-
 	))'/2~~	?r   c                  N    t        j                  t         j                  dd       y Nr   )r   r   r    r   r	   
stop_alarmzEINTRBaseTest.stop_alarmH   s    ++Q2r   c                     | j                          t        j                  t        j                  | j                         t	        j
                          y N)r)   r   r   r   r    cancel_dump_traceback_laterr$   s    r	   tearDownzEINTRBaseTest.tearDownL   s0    fnnd&7&78002r   c                 X    t         j                  df|z   }t        j                  |fi |S )Nz-c)r"   
executable
subprocessPopen)r   argskwcmd_argss       r	   r0   zEINTRBaseTest.subprocessQ   s+    NND)D0/B//r   c                 J    | j                  || j                  t        z
         y r+   )assertGreaterEqual
sleep_time	CLOCK_RES)r   elapseds     r	   check_elapsed_timez EINTRBaseTest.check_elapsed_timeU   s    9)DEr   N)__name__
__module____qualname____doc__r   r   r7   r   r%   staticmethodr)   r-   r0   r:   r(   r   r	   r   r   .   sF    ' LM J	? 3 33
0Fr   r   c                       e Zd ZdZd Zd Zd Z ej                   e	e
d      d      d        Zd Zd	 Z ej                   e	e
d
      d      d        Zd Zd Zy)OSEINTRTestz  EINTR tests for the os module. c                 B    d| j                   z  }| j                  |      S )Nzimport time; time.sleep(%r))r7   r0   )r   codes     r	   new_sleep_processzOSEINTRTest.new_sleep_process]   s    ,t>t$$r   c                     d}t        |      D cg c]  }| j                          }}t        |      D ]	  } |         |D ]  }|j                           y c c}w )N   )rangerD   wait)r   	wait_funcnum_	processesr   s         r	   _test_wait_multiplezOSEINTRTest._test_wait_multiplea   sV    7<SzBz!T++-z	BsAK  DIIK 	 Cs   Ac                 B    | j                  t        j                         y r+   )rM   osrH   r$   s    r	   	test_waitzOSEINTRTest.test_waitj   s      )r   wait3zrequires wait3()c                 (    | j                  d        y )Nc                  ,    t        j                  d      S r'   )rO   rQ   r(   r   r	   <lambda>z(OSEINTRTest.test_wait3.<locals>.<lambda>o   s    !r   )rM   r$   s    r	   
test_wait3zOSEINTRTest.test_wait3m   s      !45r   c                 h    | j                         } ||j                         |j                          y r+   )rD   pidrH   )r   rI   r   s      r	   _test_wait_singlezOSEINTRTest._test_wait_singleq   s%    %%'$((		r   c                 (    | j                  d        y )Nc                 .    t        j                  | d      S r'   )rO   waitpidrW   s    r	   rT   z*OSEINTRTest.test_waitpid.<locals>.<lambda>x   s    2::c1+=r   rX   r$   s    r	   test_waitpidzOSEINTRTest.test_waitpidw   s    =>r   wait4zrequires wait4()c                 (    | j                  d        y )Nc                 .    t        j                  | d      S r'   )rO   r_   r\   s    r	   rT   z(OSEINTRTest.test_wait4.<locals>.<lambda>|   s    288C+;r   r]   r$   s    r	   
test_wait4zOSEINTRTest.test_wait4z   s    ;<r   c                 "   t        j                         \  }}| j                  t         j                  |       g d}dj	                  dddd|z  d| j
                  z  ddd	d
df
      }| j                  |t        |      |g      }t        |      5  t        j                  |       |D ]1  }| j                  |t        j                  |t        |                   3 | j                  |j                         d       d d d        y # 1 sw Y   y xY w)N)s   hellos   worlds   spam
zimport os, sys, time zwr = int(sys.argv[1])
datas = %rsleep_time = %rzfor data in datas:z$    # let the parent block on read()    time.sleep(sleep_time)z    os.write(wr, data)pass_fdsr   )rO   pipe
addCleanupclosejoinr7   r0   strr
   assertEqualreadlenrH   )r   rdwrdatasrC   r   datas          r	   	test_readzOSEINTRTest.test_read~   s    B"%
 .yy"#5 / 2($
  tSWt<4 HHRL  rwwr3t9'=> TYY[!,	 !  s   A,DDc                    t        j                         \  }}| j                  t         j                  |       dt        j
                  z  }dj                  dddd| j                  z  dt        j
                  z  ddd	d
ddddddddddf      }| j                  |t        |      |g      }t        |      5  t        j                  |       d}|t        |      k  r4|t        j                  |t        |      |d        z  }|t        |      k  r4| j                  |j                         d       d d d        y # 1 sw Y   y xY w)N   xrd   zimport io, os, sys, timere   zrd = int(sys.argv[1])rg   zdata = b"x" * %sdata_len = len(data)z!# let the parent block on write()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))ri   r   )rO   rk   rl   rm   r   PIPE_MAX_SIZErn   r7   r0   ro   r
   rr   write
memoryviewrp   rH   )r   rs   rt   rv   rC   r   writtens          r	   
test_writezOSEINTRTest.test_write   s&   B"% g+++yy&#/!6!66"/$&93(*>;'
 , tSWt<4 HHRLGCI%288B
4(8(BCC CI%TYY[!, !  s   6AD9 D99EN)r;   r<   r=   r>   rD   rM   rP   unittest
skipUnlesshasattrrO   rU   rX   r^   rb   rw   r   r(   r   r	   rA   rA   Y   s    *%* XW-/AB6 C6? XW-/AB= C=-:$-r   rA   c                   &   e Zd ZdZ ej
                   eed      d      d        Zd Z	 ej
                   eej                  d      d      d        Z
d	 Zd
 Zd Z ej
                   eej                  d      d      d        Zd Z ej"                  dd       ej
                   eed      d      d               Zd Z ej*                  ej.                  dk(  d      d        Zd Z ej*                  ej.                  dk(  d      d        Zy)SocketEINTRTestz$ EINTR tests for the socket module. 
socketpairzneeds socketpair()c                 x   t        j                         \  }}| j                  |j                         g d}dj	                  ddddt        |j                        z  dt        |j                        z  d|z  d	| j                  z  dd
dddddddf      }|j                         }| j                  |t        |      |g      }t        |      5  |j                          |D ]$  }| j                  | ||t        |                   & | j                  |j                         d       d d d        y # 1 sw Y   y xY w)N)ry      y   zrd   import os, socket, sys, timere   fd = int(sys.argv[1])family = %ssock_type = %srf   rg   z)wr = socket.fromfd(fd, family, sock_type)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)ri   r   )socketr   rl   rm   rn   intfamilytyper7   filenor0   ro   r
   rp   rr   rH   )	r   	recv_funcrs   rt   ru   rC   fdr   rv   s	            r	   
_test_recvzSocketEINTRTest._test_recv   s   ""$B! #yy*#C		N*s277|+5 /7$6,&!
 & YY[tSWt<4 HHJ  ySY'?@ TYY[!,	 !  s   AD00D9c                 V    | j                  t        j                  j                         y r+   )r   r   recvr$   s    r	   	test_recvzSocketEINTRTest.test_recv       **+r   recvmsgzneeds recvmsg()c                 (    | j                  d        y )Nc                 *    | j                  |      d   S r'   )r   sockrv   s     r	   rT   z.SocketEINTRTest.test_recvmsg.<locals>.<lambda>   s    4<<+=a+@r   )r   r$   s    r	   test_recvmsgzSocketEINTRTest.test_recvmsg   s    @Ar   c                    t        j                         \  }}| j                  |j                         dt        j
                  dz  z  }dj                  ddddt        |j                        z  dt        |j                        z  d	| j                  z  d
t        j
                  dz  z  dddddddddddddddddf      }|j                         }| j                  |t        |      |g      }t        |      5  |j                          d}|t        |      k  r6 ||t!        |      |d        }	||	t        |      n|	z  }|t        |      k  r6| j#                  |j%                         d       d d d        y # 1 sw Y   y xY w)Ns   xyzrF   rd   r   re   r   r   r   rg   zdata = b"xyz" * %srz   z)rd = socket.fromfd(fd, family, sock_type)r   zwith rd:z$    # let the parent block on send()rh   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))ri   r   )r   r   rl   rm   r   SOCK_MAX_SIZErn   r   r   r   r7   r   r0   ro   r
   rr   r~   rp   rH   )
r   	send_funcrs   rt   rv   rC   r   r   r   sents
             r	   
_test_sendzSocketEINTRTest._test_send   sp   ""$B! ..!34yy*#C		N*s277|+/ G$9$9Q$>?"72(5%F'>C1
 6 YY[tSWt<4 HHJGCI% Z%5gh%?@3t9$> CI% TYY[!, !  s   8AE8 E88Fc                 V    | j                  t        j                  j                         y r+   )r   r   sendr$   s    r	   	test_sendzSocketEINTRTest.test_send  r   r   c                 V    | j                  t        j                  j                         y r+   )r   r   sendallr$   s    r	   test_sendallzSocketEINTRTest.test_sendall"  s    --.r   sendmsgzneeds sendmsg()c                 (    | j                  d        y )Nc                 &    | j                  |g      S r+   )r   r   s     r	   rT   z.SocketEINTRTest.test_sendmsg.<locals>.<lambda>'  s    4<<+?r   )r   r$   s    r	   test_sendmsgzSocketEINTRTest.test_sendmsg%  s    ?@r   c                 
   t        j                  t        j                  df      }| j	                  |j
                         |j                         d   }dj                  dddt        j                  z  d|z  d| j                  z  dd	d
ddf
      }| j                  |      }t        |      5  |j                         \  }}|j                          | j                  |j                         d       d d d        y # 1 sw Y   y xY w)Nr   r   rd   zimport socket, timere   z	host = %rz	port = %srg   z# let parent block on accept()r{   z,with socket.create_connection((host, port)):rh   )r   create_serverr   HOSTrl   rm   getsocknamern   r7   r0   r
   acceptrp   rH   )r   r   portrC   r   client_sockrK   s          r	   test_acceptzSocketEINTRTest.test_accept)  s    ##]%7%7$;<

#!!$yy!-,,,$/,$:(
  t$4 ![[]NKTYY[!, !  s   ,AC99D
   rF   mkfifozneeds mkfifo()c                    t         j                  }t        j                  |       	 t        j                  |       | j                  t         j                  |       dj                  ddd|z  d| j                  z  dddd|f	      }| j                  |      }t        |      5   ||       | j                  |j                         d	       d d d        y # t
        $ r}| j                  d|z         Y d }~d }~ww xY w# 1 sw Y   y xY w)
Nzos.mkfifo(): %srd   import os, timere   z	path = %arg   z# let the parent blockr{   r   )r   TESTFNunlinkrO   r   PermissionErrorskipTestrl   rn   r7   r0   r
   rp   rH   )r   do_open_close_readerdo_open_close_writerfilenameerC   r   s          r	   
_test_openzSocketEINTRTest._test_openE  s     ## 	"	1IIh 		(((3yy("/$$ 

 
 t$4  *TYY[!, ! #  	1MM+a/00	1" ! s#   C ")C>	C;C66C;>Dc                 <    t        |d      }|j                          y )Nw)openrm   )r   pathfps      r	   python_openzSocketEINTRTest.python_opend  s    $_

r   darwinz+hangs under macOS; see bpo-25234, bpo-35363c                 <    | j                  d| j                         y )Nzfp = open(path, 'r')
fp.close())r   r   r$   s    r	   	test_openzSocketEINTRTest.test_openh  s     	:((	*r   c                 v    t        j                  |t         j                        }t        j                  |       y r+   )rO   r   O_WRONLYrm   )r   r   r   s      r	   os_openzSocketEINTRTest.os_openn  s!    WWT2;;'
r   c                 <    | j                  d| j                         y )Nz,fd = os.open(path, os.O_RDONLY)
os.close(fd))r   r   r$   s    r	   test_os_openzSocketEINTRTest.test_os_openr  s     	G	&r   N)r;   r<   r=   r>   r   r   r   r   r   r   r   r   r   r   r   r   r   requires_freebsd_versionrO   r   r   skipIfr"   platformr   r   r   r(   r   r	   r   r      sY   .X68LM!- N!-F, X	:<MNB OB,-\,/ X	:<MNA OA-8 &W%%b!,XX.0@A- B --: X__S\\X-BD*D* X__S\\X-BD&D&r   r   c                       e Zd ZdZd Zy)TimeEINTRTestz" EINTR tests for the time module. c                     t        j                         }t        j                  | j                         | j	                          t        j                         |z
  }| j                  |       y r+   )time	monotonicsleepr7   r)   r:   r   t0dts      r	   
test_sleepzTimeEINTRTest.test_sleep}  sG    ^^

4??#^^"#r   N)r;   r<   r=   r>   r   r(   r   r	   r   r   y  s
    ,$r   r   pthread_sigmaskzneed signal.pthread_sigmask()c                       e Zd ZdZd Z ej                   eed      d      d        Z	 ej                   eed      d      d        Z
y)	SignalEINTRTestz$ EINTR tests for the signal module. c                    t         j                  }t        j                         }t        j                   |d       }| j	                  t         j                   ||       dj                  ddt        j                         z  dt        |      z  d| j                  z  ddf      }t        j                  t         j                  |g      }| j	                  t         j                  t         j                  |g       | j                  |      }t        |      5   ||       d d d        | j                  |j                         d	       y # 1 sw Y   *xY w)
Nc                       y r+   r(   )r2   s    r	   rT   z/SignalEINTRTest.check_sigwait.<locals>.<lambda>  s    $r   rd   r   zpid = %szsignum = %srg   r{   zos.kill(pid, signum)r   )r   SIGUSR1rO   getpidrl   rn   r   r7   r   	SIG_BLOCKSIG_UNBLOCKr0   r
   rp   rH   )r   rI   r   rW   old_handlerrC   old_maskr   s           r	   check_sigwaitzSignalEINTRTest.check_sigwait  s    iikmmF,>?v{;yy$CK'/$"
  ))&*:*:VHE..0B0BVHMt$4 f ! 	a( ! s   	EEsigwaitinfozneed signal.sigwaitinfo()c                 ,    d }| j                  |       y )Nc                 0    t        j                  | g       y r+   )r   r   r   s    r	   rI   z3SignalEINTRTest.test_sigwaitinfo.<locals>.wait_func  s    x(r   r   r   rI   s     r	   test_sigwaitinfoz SignalEINTRTest.test_sigwaitinfo  s    	) 	9%r   sigtimedwaitc                 ,    d }| j                  |       y )Nc                 2    t        j                  | gd       y )Ng      ^@)r   r   r   s    r	   rI   z4SignalEINTRTest.test_sigtimedwait.<locals>.wait_func  s    %0r   r   r   s     r	   test_sigtimedwaitz!SignalEINTRTest.test_sigtimedwait  s    	1 	9%r   N)r;   r<   r=   r>   r   r   r   r   r   r   r   r(   r   r	   r   r     sf     /)2 X746&6& X846&6&r   r   c                   \   e Zd ZdZd Z ej                  ej                  dk(  d       ej                   e
ed      d      d               Z ej                   e
ed      d	      d
        Z ej                   e
ed      d      d        Z ej                   e
ed      d      d        Zy)SelectEINTRTestz$ EINTR tests for the select module. c                     t        j                         }t        j                  g g g | j                         t        j                         |z
  }| j	                          | j                  |       y r+   )r   r   selectr7   r)   r:   r   s      r	   test_selectzSelectEINTRTest.test_select  sM    ^^b"b$//2^^"#r   r   z(poll may fail on macOS; see issue #28087pollzneed select.pollc                     t        j                         }t        j                         }|j                  | j                  dz         t        j                         |z
  }| j                          | j                  |       y Ng     @@)r   r   r   r   r7   r)   r:   r   pollerr   r   s       r	   	test_pollzSelectEINTRTest.test_poll  sY     ^^DOOc)*^^"#r   epollzneed select.epollc                 0   t        j                         }| j                  |j                         t	        j
                         }|j                  | j                         t	        j
                         |z
  }| j                          | j                  |       y r+   )
r   r  rl   rm   r   r   r   r7   r)   r:   r   s       r	   
test_epollzSelectEINTRTest.test_epoll  sb    %^^DOO$^^"#r   kqueuezneed select.kqueuec                 4   t        j                         }| j                  |j                         t	        j
                         }|j                  d d| j                         t	        j
                         |z
  }| j                          | j                  |       y r   )
r   r  rl   rm   r   r   controlr7   r)   r:   )r   r  r   r   s       r	   test_kqueuezSelectEINTRTest.test_kqueue  sf    %^^tQ0^^"#r   devpollzneed select.devpollc                 6   t        j                         }| j                  |j                         t	        j
                         }|j                  | j                  dz         t	        j
                         |z
  }| j                          | j                  |       y r   )
r   r	  rl   rm   r   r   r   r7   r)   r:   r   s       r	   test_devpollzSelectEINTRTest.test_devpoll  sh    !%^^DOOc)*^^"#r   N)r;   r<   r=   r>   r   r   r   r"   r   r   r   r   r  r  r  r  r(   r   r	   r   r     s    .$ X__S\\X-?AX02DE$ FA$ X13FG$ H$ X24HI$ J$ X35JK$ L$r   r   c                   n    e Zd Zd Z ej
                   ej                         dk(  d      d        Zd Z	y)FCNTLEINTRTestc                    | j                  t        j                  t        j                         t	        j
                         \  }}t	        j
                         \  }}||||fD ]"  }| j                  t        j                  |       $ t        j                  dt        j                   d| d| d| d| j                   d      }| j                  |||g      }	t        |	      5  t        t        j                  d      5 }
t	        j                  |d	      }| j                  |d
       t        j                          }t	        j"                  |d        ||
t$        j&                         t        j                          |z
  }| j)                          | j+                  |       d d d        |	j-                          d d d        y # 1 sw Y   "xY w# 1 sw Y   y xY w)Nz;
            import fcntl, os, time
            with open('z%', 'wb') as f:
                fcntl.z,(f, fcntl.LOCK_EX)
                os.write(z%, b"ok")
                _ = os.read(z;, 2)  # wait for parent process
                time.sleep(z
)
        ri   wb   s   oks   go)rl   r   r   r   rO   rk   rm   textwrapdedentr7   r0   r
   r   rq   rp   r   r   r}   fcntlLOCK_EXr)   r:   rH   )r   	lock_func	lock_namerd1wr1rd2wr2r   rC   r   fok
start_timer   s                 r	   _lockzFCNTLEINTRTest._lock  s   	(()*:*:;779S779SS#&BOOBHHb) ' $!(() * k "  E " OO, -	   tsCj94 i&&-WWS!_  U+ "^^-
e$
 !U]]+^^%
2!''+ .  IIK# ! -- ! s%   %G B"G"GG	GGAIXzAIX returns PermissionErrorc                 D    | j                  t        j                  d       y )Nlockf)r  r  r!  r$   s    r	   
test_lockfzFCNTLEINTRTest.test_lockf  s    

5;;(r   c                 D    | j                  t        j                  d       y )Nflock)r  r  r$  r$   s    r	   
test_flockzFCNTLEINTRTest.test_flock  s    

5;;(r   N)
r;   r<   r=   r  r   r   r   systemr"  r%  r(   r   r	   r  r    s>     H X___X__&%/1NO) P))r   r  __main__)"r>   
contextlibr    r  rO   r   r   r   r   r0   r"   r  r   r   testr   test.supportr   r   r8   contextmanagerr
   r   r   TestCaser   rA   r   r   r   r   r  r;   mainr(   r   r	   <module>r.     s      	      
     " &
 	   WV[13IJ'FH%% 'F K'FT WV[13IJe-- e- Ke-P WV[13IJs&m s& Ks&l WV[13IJ$M $ K$ WV[13IJ WV%6746*&m *&6 K
*&Z WV[13IJ5$m 5$ K5$p*)] *)Z zHMMO r   