@@ -18,7 +18,12 @@ pub(crate) mod _signal {
1818 Py ,
1919 convert:: { IntoPyException , TryFromBorrowedObject } ,
2020 } ;
21- use crate :: { PyObjectRef , PyResult , VirtualMachine , signal} ;
21+ use crate :: {
22+ PyObjectRef , PyResult , VirtualMachine ,
23+ builtins:: PyTypeRef ,
24+ function:: { ArgIntoFloat , OptionalArg } ,
25+ signal,
26+ } ;
2227 use std:: sync:: atomic:: { self , Ordering } ;
2328
2429 #[ cfg( any( unix, windows) ) ]
@@ -114,6 +119,21 @@ pub(crate) mod _signal {
114119 #[ pyattr]
115120 use libc:: { SIGPWR , SIGSTKFLT } ;
116121
122+ // Interval timer constants
123+ #[ cfg( unix) ]
124+ #[ pyattr]
125+ use libc:: { ITIMER_PROF , ITIMER_REAL , ITIMER_VIRTUAL } ;
126+
127+ #[ cfg( unix) ]
128+ #[ pyattr( name = "ItimerError" , once) ]
129+ fn itimer_error ( vm : & VirtualMachine ) -> PyTypeRef {
130+ vm. ctx . new_exception_type (
131+ "signal" ,
132+ "ItimerError" ,
133+ Some ( vec ! [ vm. ctx. exceptions. os_error. to_owned( ) ] ) ,
134+ )
135+ }
136+
117137 #[ cfg( any( unix, windows) ) ]
118138 pub ( super ) fn init_signal_handlers (
119139 module : & Py < crate :: builtins:: PyModule > ,
@@ -216,6 +236,74 @@ pub(crate) mod _signal {
216236 prev_time. unwrap_or ( 0 )
217237 }
218238
239+ #[ cfg( unix) ]
240+ #[ pyfunction]
241+ fn pause ( vm : & VirtualMachine ) -> PyResult < ( ) > {
242+ unsafe { libc:: pause ( ) } ;
243+ signal:: check_signals ( vm) ?;
244+ Ok ( ( ) )
245+ }
246+
247+ #[ cfg( unix) ]
248+ fn timeval_to_double ( tv : & libc:: timeval ) -> f64 {
249+ tv. tv_sec as f64 + ( tv. tv_usec as f64 / 1_000_000.0 )
250+ }
251+
252+ #[ cfg( unix) ]
253+ fn double_to_timeval ( val : f64 ) -> libc:: timeval {
254+ libc:: timeval {
255+ tv_sec : val. trunc ( ) as _ ,
256+ tv_usec : ( ( val. fract ( ) ) * 1_000_000.0 ) as _ ,
257+ }
258+ }
259+
260+ #[ cfg( unix) ]
261+ fn itimerval_to_tuple ( it : & libc:: itimerval ) -> ( f64 , f64 ) {
262+ (
263+ timeval_to_double ( & it. it_value ) ,
264+ timeval_to_double ( & it. it_interval ) ,
265+ )
266+ }
267+
268+ #[ cfg( unix) ]
269+ #[ pyfunction]
270+ fn setitimer (
271+ which : i32 ,
272+ seconds : ArgIntoFloat ,
273+ interval : OptionalArg < ArgIntoFloat > ,
274+ vm : & VirtualMachine ,
275+ ) -> PyResult < ( f64 , f64 ) > {
276+ let seconds: f64 = seconds. into ( ) ;
277+ let interval: f64 = interval. map ( |v| v. into ( ) ) . unwrap_or ( 0.0 ) ;
278+ let new = libc:: itimerval {
279+ it_value : double_to_timeval ( seconds) ,
280+ it_interval : double_to_timeval ( interval) ,
281+ } ;
282+ let mut old = std:: mem:: MaybeUninit :: < libc:: itimerval > :: uninit ( ) ;
283+ let ret = unsafe { libc:: setitimer ( which, & new, old. as_mut_ptr ( ) ) } ;
284+ if ret != 0 {
285+ let err = std:: io:: Error :: last_os_error ( ) ;
286+ let itimer_error = itimer_error ( vm) ;
287+ return Err ( vm. new_exception_msg ( itimer_error, err. to_string ( ) ) ) ;
288+ }
289+ let old = unsafe { old. assume_init ( ) } ;
290+ Ok ( itimerval_to_tuple ( & old) )
291+ }
292+
293+ #[ cfg( unix) ]
294+ #[ pyfunction]
295+ fn getitimer ( which : i32 , vm : & VirtualMachine ) -> PyResult < ( f64 , f64 ) > {
296+ let mut old = std:: mem:: MaybeUninit :: < libc:: itimerval > :: uninit ( ) ;
297+ let ret = unsafe { libc:: getitimer ( which, old. as_mut_ptr ( ) ) } ;
298+ if ret != 0 {
299+ let err = std:: io:: Error :: last_os_error ( ) ;
300+ let itimer_error = itimer_error ( vm) ;
301+ return Err ( vm. new_exception_msg ( itimer_error, err. to_string ( ) ) ) ;
302+ }
303+ let old = unsafe { old. assume_init ( ) } ;
304+ Ok ( itimerval_to_tuple ( & old) )
305+ }
306+
219307 #[ pyfunction]
220308 fn default_int_handler (
221309 _signum : PyObjectRef ,
0 commit comments