@@ -14,7 +14,7 @@ pub(crate) fn make_module(vm: &VirtualMachine) -> PyRef<PyModule> {
1414pub ( crate ) mod module {
1515 use crate :: {
1616 PyResult , TryFromObject , VirtualMachine ,
17- builtins:: { PyDictRef , PyListRef , PyStrRef , PyTupleRef } ,
17+ builtins:: { PyBaseExceptionRef , PyDictRef , PyListRef , PyStrRef , PyTupleRef } ,
1818 common:: { crt_fd, os:: last_os_error, suppress_iph} ,
1919 convert:: ToPyException ,
2020 function:: { Either , OptionalArg } ,
@@ -488,6 +488,13 @@ pub(crate) mod module {
488488 fn _dup2 ( fd : i32 , fd2 : i32 ) -> i32 ;
489489 }
490490
491+ /// Close fd and convert error to PyException (PEP 446 cleanup)
492+ #[ cold]
493+ fn close_fd_and_raise ( fd : i32 , err : std:: io:: Error , vm : & VirtualMachine ) -> PyBaseExceptionRef {
494+ let _ = unsafe { crt_fd:: Owned :: from_raw ( fd) } ;
495+ err. to_pyexception ( vm)
496+ }
497+
491498 #[ pyfunction]
492499 fn umask ( mask : i32 , vm : & VirtualMachine ) -> PyResult < i32 > {
493500 let result = unsafe { _umask ( mask) } ;
@@ -504,11 +511,10 @@ pub(crate) mod module {
504511 if fd2 < 0 {
505512 return Err ( errno_err ( vm) ) ;
506513 }
507- // Set the new fd as non-inheritable
508514 let borrowed = unsafe { crt_fd:: Borrowed :: borrow_raw ( fd2) } ;
509- let handle = crt_fd:: as_handle ( borrowed) . map_err ( |e| e . to_pyexception ( vm) ) ?;
515+ let handle = crt_fd:: as_handle ( borrowed) . map_err ( |e| close_fd_and_raise ( fd2 , e , vm) ) ?;
510516 raw_set_handle_inheritable ( handle. as_raw_handle ( ) as _ , false )
511- . map_err ( |e| e . to_pyexception ( vm) ) ?;
517+ . map_err ( |e| close_fd_and_raise ( fd2 , e , vm) ) ?;
512518 Ok ( fd2)
513519 }
514520
@@ -530,9 +536,10 @@ pub(crate) mod module {
530536 }
531537 if !args. inheritable {
532538 let borrowed = unsafe { crt_fd:: Borrowed :: borrow_raw ( args. fd2 ) } ;
533- let handle = crt_fd:: as_handle ( borrowed) . map_err ( |e| e. to_pyexception ( vm) ) ?;
539+ let handle =
540+ crt_fd:: as_handle ( borrowed) . map_err ( |e| close_fd_and_raise ( args. fd2 , e, vm) ) ?;
534541 raw_set_handle_inheritable ( handle. as_raw_handle ( ) as _ , false )
535- . map_err ( |e| e . to_pyexception ( vm) ) ?;
542+ . map_err ( |e| close_fd_and_raise ( args . fd2 , e , vm) ) ?;
536543 }
537544 Ok ( args. fd2 )
538545 }
0 commit comments