@@ -111,11 +111,15 @@ mod decl {
111111
112112 fn collect_frame_info ( frame : & crate :: vm:: PyRef < Frame > ) -> String {
113113 let func_name = truncate_name ( frame. code . obj_name . as_str ( ) ) ;
114+ // If lasti is 0, execution hasn't started yet - use first line number or 1
115+ let line = if frame. lasti ( ) == 0 {
116+ frame. code . first_line_number . map ( |n| n. get ( ) ) . unwrap_or ( 1 )
117+ } else {
118+ frame. current_location ( ) . line . get ( )
119+ } ;
114120 format ! (
115121 " File \" {}\" , line {} in {}" ,
116- frame. code. source_path,
117- frame. current_location( ) . line,
118- func_name
122+ frame. code. source_path, line, func_name
119123 )
120124 }
121125
@@ -211,7 +215,7 @@ mod decl {
211215 fn install_fatal_handlers ( _vm : & VirtualMachine ) {
212216 for ( idx, ( signum, _) ) in FATAL_SIGNALS . iter ( ) . enumerate ( ) {
213217 let mut action: libc:: sigaction = unsafe { std:: mem:: zeroed ( ) } ;
214- action. sa_sigaction = faulthandler_fatal_error as usize ;
218+ action. sa_sigaction = faulthandler_fatal_error as libc :: sighandler_t ;
215219 action. sa_flags = libc:: SA_NODEFER ;
216220
217221 unsafe {
@@ -246,11 +250,13 @@ mod decl {
246250
247251 // For SIGSEGV on Windows, need to loop raise
248252 if signum == libc:: SIGSEGV {
249- loop {
253+ for _ in 0 .. 100 {
250254 unsafe {
251255 libc:: raise ( signum) ;
252256 }
253257 }
258+ // Fallback if signal doesn't terminate the process
259+ std:: process:: exit ( 128 + signum) ;
254260 } else {
255261 unsafe {
256262 libc:: raise ( signum) ;
@@ -367,36 +373,25 @@ mod decl {
367373 let ( lock, cvar) = & * state;
368374
369375 loop {
370- let ( timeout, repeat, exit, fd, header, cancelled) = {
371- let guard = lock. lock ( ) . unwrap ( ) ;
372- if guard. cancel {
373- return ;
374- }
375- (
376- Duration :: from_micros ( guard. timeout_us ) ,
377- guard. repeat ,
378- guard. exit ,
379- guard. fd ,
380- guard. header . clone ( ) ,
381- guard. cancel ,
382- )
383- } ;
384-
385- if cancelled {
376+ // Hold lock across wait_timeout to avoid race condition
377+ let mut guard = lock. lock ( ) . unwrap ( ) ;
378+ if guard. cancel {
386379 return ;
387380 }
381+ let timeout = Duration :: from_micros ( guard. timeout_us ) ;
382+ let result = cvar. wait_timeout ( guard, timeout) . unwrap ( ) ;
383+ guard = result. 0 ;
388384
389- // Wait for timeout or cancellation
390- let result = {
391- let guard = lock. lock ( ) . unwrap ( ) ;
392- cvar. wait_timeout ( guard, timeout) . unwrap ( )
393- } ;
394-
395- // Check if cancelled
396- if result. 0 . cancel {
385+ // Check if cancelled after wait
386+ if guard. cancel {
397387 return ;
398388 }
399389
390+ // Extract values before releasing lock for I/O
391+ let ( repeat, exit, fd, header) =
392+ ( guard. repeat , guard. exit , guard. fd , guard. header . clone ( ) ) ;
393+ drop ( guard) ; // Release lock before I/O
394+
400395 // Timeout occurred, dump traceback
401396 #[ cfg( not( target_arch = "wasm32" ) ) ]
402397 {
@@ -652,45 +647,6 @@ mod decl {
652647 Ok ( ( ) )
653648 }
654649
655- #[ cfg( unix) ]
656- fn get_fd_from_file ( file : OptionalArg < PyObjectRef > , vm : & VirtualMachine ) -> PyResult < i32 > {
657- match file {
658- OptionalArg :: Present ( f) => {
659- // Check if it's an integer (file descriptor)
660- if let Ok ( fd) = f. try_to_value :: < i32 > ( vm) {
661- if fd < 0 {
662- return Err (
663- vm. new_value_error ( "file is not a valid file descriptor" . to_owned ( ) )
664- ) ;
665- }
666- return Ok ( fd) ;
667- }
668- // Try to get fileno() from file object
669- let fileno = vm. call_method ( & f, "fileno" , ( ) ) ?;
670- let fd: i32 = fileno. try_to_value ( vm) ?;
671- if fd < 0 {
672- return Err (
673- vm. new_value_error ( "file is not a valid file descriptor" . to_owned ( ) )
674- ) ;
675- }
676- // Try to flush the file
677- let _ = vm. call_method ( & f, "flush" , ( ) ) ;
678- Ok ( fd)
679- }
680- OptionalArg :: Missing => {
681- // Get sys.stderr
682- let stderr = vm. sys_module . get_attr ( "stderr" , vm) ?;
683- if vm. is_none ( & stderr) {
684- return Err ( vm. new_runtime_error ( "sys.stderr is None" . to_owned ( ) ) ) ;
685- }
686- let fileno = vm. call_method ( & stderr, "fileno" , ( ) ) ?;
687- let fd: i32 = fileno. try_to_value ( vm) ?;
688- let _ = vm. call_method ( & stderr, "flush" , ( ) ) ;
689- Ok ( fd)
690- }
691- }
692- }
693-
694650 #[ cfg( unix) ]
695651 #[ derive( FromArgs ) ]
696652 #[ allow( unused) ]
@@ -710,7 +666,7 @@ mod decl {
710666 fn register ( args : RegisterArgs , vm : & VirtualMachine ) -> PyResult < ( ) > {
711667 check_signum ( args. signum , vm) ?;
712668
713- let fd = get_fd_from_file ( args. file , vm) ?;
669+ let fd = get_fd_from_file_opt ( args. file , vm) ?;
714670
715671 let signum = args. signum as usize ;
716672
0 commit comments