@@ -7,8 +7,6 @@ use std::collections::HashMap;
77use std:: ffi:: OsString ;
88use std:: io:: Write ;
99#[ cfg( unix) ]
10- use std:: os:: fd:: FromRawFd ;
11- #[ cfg( unix) ]
1210use std:: os:: unix:: prelude:: ExitStatusExt ;
1311#[ cfg( unix) ]
1412use std:: os:: unix:: process:: CommandExt ;
@@ -81,14 +79,12 @@ impl Stdio {
8179}
8280
8381#[ derive( Copy , Clone , Eq , PartialEq ) ]
84- pub enum StdioOrFdOrRid {
82+ pub enum StdioOrRid {
8583 Stdio ( Stdio ) ,
86- /// A raw file descriptor (e.g. from Node's `fs.openSync`).
87- Fd ( i32 ) ,
8884 Rid ( ResourceId ) ,
8985}
9086
91- impl < ' de > Deserialize < ' de > for StdioOrFdOrRid {
87+ impl < ' de > Deserialize < ' de > for StdioOrRid {
9288 fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
9389 where
9490 D : serde:: Deserializer < ' de > ,
@@ -97,69 +93,38 @@ impl<'de> Deserialize<'de> for StdioOrFdOrRid {
9793 let value = Value :: deserialize ( deserializer) ?;
9894 match value {
9995 Value :: String ( val) => match val. as_str ( ) {
100- "inherit" => Ok ( StdioOrFdOrRid :: Stdio ( Stdio :: Inherit ) ) ,
101- "piped" => Ok ( StdioOrFdOrRid :: Stdio ( Stdio :: Piped ) ) ,
102- "null" => Ok ( StdioOrFdOrRid :: Stdio ( Stdio :: Null ) ) ,
96+ "inherit" => Ok ( StdioOrRid :: Stdio ( Stdio :: Inherit ) ) ,
97+ "piped" => Ok ( StdioOrRid :: Stdio ( Stdio :: Piped ) ) ,
98+ "null" => Ok ( StdioOrRid :: Stdio ( Stdio :: Null ) ) ,
10399 "ipc_for_internal_use" => {
104- Ok ( StdioOrFdOrRid :: Stdio ( Stdio :: IpcForInternalUse ) )
100+ Ok ( StdioOrRid :: Stdio ( Stdio :: IpcForInternalUse ) )
105101 }
106102 val => Err ( serde:: de:: Error :: unknown_variant (
107103 val,
108104 & [ "inherit" , "piped" , "null" ] ,
109105 ) ) ,
110106 } ,
111- Value :: Number ( val) => match val. as_i64 ( ) {
112- Some ( val) if val >= 0 && val <= i32 :: MAX as i64 => {
113- Ok ( StdioOrFdOrRid :: Fd ( val as i32 ) )
107+ Value :: Number ( val) => match val. as_u64 ( ) {
108+ Some ( val) if val <= ResourceId :: MAX as u64 => {
109+ Ok ( StdioOrRid :: Rid ( val as ResourceId ) )
114110 }
115- _ => Err ( serde:: de:: Error :: custom ( "Expected a non-negative integer" ) ) ,
111+ _ => Err ( serde:: de:: Error :: custom ( "Expected a positive integer" ) ) ,
116112 } ,
117113 _ => Err ( serde:: de:: Error :: custom (
118- r#"Expected a file descriptor , "inherit", "piped", or "null""# ,
114+ r#"Expected a resource id , "inherit", "piped", or "null""# ,
119115 ) ) ,
120116 }
121117 }
122118}
123119
124- impl StdioOrFdOrRid {
120+ impl StdioOrRid {
125121 pub fn as_stdio (
126122 & self ,
127123 state : & mut OpState ,
128124 ) -> Result < StdStdio , ProcessError > {
129125 match & self {
130- StdioOrFdOrRid :: Stdio ( val) => Ok ( val. as_stdio ( ) ) ,
131- StdioOrFdOrRid :: Fd ( fd) => {
132- // Convert a raw FD to a Stdio by dup'ing it into a std::fs::File.
133- #[ cfg( unix) ]
134- {
135- // SAFETY: libc::dup is safe to call with any fd; returns -1 on error.
136- let duped = unsafe { libc:: dup ( * fd) } ;
137- if duped < 0 {
138- return Err ( ProcessError :: Io ( std:: io:: Error :: last_os_error ( ) ) ) ;
139- }
140- // SAFETY: duped is a valid fd we own (just created by dup).
141- Ok ( unsafe { std:: fs:: File :: from_raw_fd ( duped) } . into ( ) )
142- }
143- #[ cfg( windows) ]
144- {
145- // SAFETY: get_osfhandle converts a CRT fd to a Windows HANDLE; returns -1 on error.
146- let handle = unsafe { libc:: get_osfhandle ( * fd) } ;
147- if handle == -1 {
148- return Err ( ProcessError :: Io ( std:: io:: Error :: last_os_error ( ) ) ) ;
149- }
150- // SAFETY: handle is a valid Windows HANDLE (verified non-negative above).
151- // BorrowedHandle does not take ownership.
152- let borrowed = unsafe {
153- std:: os:: windows:: io:: BorrowedHandle :: borrow_raw (
154- handle as * mut std:: ffi:: c_void ,
155- )
156- } ;
157- let owned =
158- borrowed. try_clone_to_owned ( ) . map_err ( ProcessError :: Io ) ?;
159- Ok ( std:: fs:: File :: from ( owned) . into ( ) )
160- }
161- }
162- StdioOrFdOrRid :: Rid ( rid) => {
126+ StdioOrRid :: Stdio ( val) => Ok ( val. as_stdio ( ) ) ,
127+ StdioOrRid :: Rid ( rid) => {
163128 Ok ( FileResource :: with_file ( state, * rid, |file| {
164129 file. as_stdio ( ) . map_err ( deno_error:: JsErrorBox :: from_err)
165130 } ) ?)
@@ -168,7 +133,7 @@ impl StdioOrFdOrRid {
168133 }
169134
170135 pub fn is_ipc ( & self ) -> bool {
171- matches ! ( self , StdioOrFdOrRid :: Stdio ( Stdio :: IpcForInternalUse ) )
136+ matches ! ( self , StdioOrRid :: Stdio ( Stdio :: IpcForInternalUse ) )
172137 }
173138}
174139
@@ -283,7 +248,7 @@ pub struct SpawnArgs {
283248
284249 input : Option < JsBuffer > ,
285250
286- extra_stdio : Vec < StdioOrFdOrRid > ,
251+ extra_stdio : Vec < Stdio > ,
287252 detached : bool ,
288253 needs_npm_process_state : bool ,
289254 #[ cfg( unix) ]
@@ -384,9 +349,9 @@ pub enum ProcessError {
384349#[ derive( Deserialize ) ]
385350#[ serde( rename_all = "camelCase" ) ]
386351pub struct ChildStdio {
387- stdin : StdioOrFdOrRid ,
388- stdout : StdioOrFdOrRid ,
389- stderr : StdioOrFdOrRid ,
352+ stdin : StdioOrRid ,
353+ stdout : StdioOrRid ,
354+ stderr : StdioOrRid ,
390355}
391356
392357#[ derive( ToV8 ) ]
@@ -553,15 +518,11 @@ fn create_command(
553518 }
554519
555520 command. stdout ( match args. stdio . stdout {
556- StdioOrFdOrRid :: Stdio ( Stdio :: Inherit ) => {
557- StdioOrFdOrRid :: Rid ( 1 ) . as_stdio ( state) ?
558- }
521+ StdioOrRid :: Stdio ( Stdio :: Inherit ) => StdioOrRid :: Rid ( 1 ) . as_stdio ( state) ?,
559522 value => value. as_stdio ( state) ?,
560523 } ) ;
561524 command. stderr ( match args. stdio . stderr {
562- StdioOrFdOrRid :: Stdio ( Stdio :: Inherit ) => {
563- StdioOrFdOrRid :: Rid ( 2 ) . as_stdio ( state) ?
564- }
525+ StdioOrRid :: Stdio ( Stdio :: Inherit ) => StdioOrRid :: Rid ( 2 ) . as_stdio ( state) ?,
565526 value => value. as_stdio ( state) ?,
566527 } ) ;
567528
@@ -617,36 +578,26 @@ fn create_command(
617578 // index 0 in `extra_stdio` actually refers to fd 3
618579 // because we handle stdin,stdout,stderr specially
619580 let fd = ( i + 3 ) as i32 ;
620- match stdio {
621- StdioOrFdOrRid :: Stdio ( Stdio :: Piped ) => {
622- let ( fd1, fd2) = deno_io:: bi_pipe_pair_raw ( ) ?;
623- fds_to_dup. push ( ( fd2, fd) ) ;
624- fds_to_close. push ( fd2) ;
625- let rid = state. resource_table . add (
626- match deno_io:: BiPipeResource :: from_raw_handle ( fd1) {
627- Ok ( v) => v,
628- Err ( e) => {
629- log:: warn!(
630- "Failed to open bidirectional pipe for fd {fd}: {e}"
631- ) ;
632- extra_pipe_rids. push ( None ) ;
633- continue ;
634- }
635- } ,
636- ) ;
637- extra_pipe_rids. push ( Some ( rid) ) ;
638- }
639- StdioOrFdOrRid :: Fd ( raw_fd) => {
640- // Raw file descriptor (from fs.openSync etc.)
641- // dup2 it to the target fd in the child process.
642- // The caller retains ownership of raw_fd so we don't
643- // add it to fds_to_close.
644- fds_to_dup. push ( ( raw_fd, fd) ) ;
645- extra_pipe_rids. push ( None ) ;
646- }
647- _ => {
648- extra_pipe_rids. push ( None ) ;
649- }
581+ // TODO(nathanwhit): handle inherited, but this relies on the parent process having
582+ // fds open already. since we don't generally support dealing with raw fds,
583+ // we can't properly support this
584+ if matches ! ( stdio, Stdio :: Piped ) {
585+ let ( fd1, fd2) = deno_io:: bi_pipe_pair_raw ( ) ?;
586+ fds_to_dup. push ( ( fd2, fd) ) ;
587+ fds_to_close. push ( fd2) ;
588+ let rid = state. resource_table . add (
589+ match deno_io:: BiPipeResource :: from_raw_handle ( fd1) {
590+ Ok ( v) => v,
591+ Err ( e) => {
592+ log:: warn!( "Failed to open bidirectional pipe for fd {fd}: {e}" ) ;
593+ extra_pipe_rids. push ( None ) ;
594+ continue ;
595+ }
596+ } ,
597+ ) ;
598+ extra_pipe_rids. push ( Some ( rid) ) ;
599+ } else {
600+ extra_pipe_rids. push ( None ) ;
650601 }
651602 }
652603
@@ -719,41 +670,28 @@ fn create_command(
719670 // index 0 in `extra_stdio` actually refers to fd 3
720671 // because we handle stdin,stdout,stderr specially
721672 let fd = ( i + 3 ) as i32 ;
722- match stdio {
723- StdioOrFdOrRid :: Stdio ( Stdio :: Piped ) => {
724- let ( fd1, fd2) = deno_io:: bi_pipe_pair_raw ( ) ?;
725- handles_to_close. push ( fd2) ;
726- let rid = state. resource_table . add (
727- match deno_io:: BiPipeResource :: from_raw_handle ( fd1) {
728- Ok ( v) => v,
729- Err ( e) => {
730- log:: warn!(
731- "Failed to open bidirectional pipe for fd {fd}: {e}"
732- ) ;
733- extra_pipe_rids. push ( None ) ;
734- continue ;
735- }
736- } ,
737- ) ;
738- command. extra_handle ( Some ( fd2) ) ;
739- extra_pipe_rids. push ( Some ( rid) ) ;
740- }
741- StdioOrFdOrRid :: Fd ( raw_fd) => {
742- // SAFETY: get_osfhandle converts a CRT fd to a Windows HANDLE; returns -1 on error.
743- let handle = unsafe { libc:: get_osfhandle ( raw_fd) } ;
744- if handle != -1 {
745- command. extra_handle ( Some ( handle as _ ) ) ;
746- } else {
747- command. extra_handle ( None ) ;
748- }
749- extra_pipe_rids. push ( None ) ;
750- }
751- _ => {
752- // No handle -- push an empty slot so subsequent handles
753- // get the right fd indices.
754- command. extra_handle ( None ) ;
755- extra_pipe_rids. push ( None ) ;
756- }
673+ // TODO(nathanwhit): handle inherited, but this relies on the parent process having
674+ // fds open already. since we don't generally support dealing with raw fds,
675+ // we can't properly support this
676+ if matches ! ( stdio, Stdio :: Piped ) {
677+ let ( fd1, fd2) = deno_io:: bi_pipe_pair_raw ( ) ?;
678+ handles_to_close. push ( fd2) ;
679+ let rid = state. resource_table . add (
680+ match deno_io:: BiPipeResource :: from_raw_handle ( fd1) {
681+ Ok ( v) => v,
682+ Err ( e) => {
683+ log:: warn!( "Failed to open bidirectional pipe for fd {fd}: {e}" ) ;
684+ extra_pipe_rids. push ( None ) ;
685+ continue ;
686+ }
687+ } ,
688+ ) ;
689+ command. extra_handle ( Some ( fd2) ) ;
690+ extra_pipe_rids. push ( Some ( rid) ) ;
691+ } else {
692+ // no handle, push an empty handle so we need get the right fds for following handles
693+ command. extra_handle ( None ) ;
694+ extra_pipe_rids. push ( None ) ;
757695 }
758696 }
759697
@@ -1177,8 +1115,8 @@ fn op_spawn_sync(
11771115 state : & mut OpState ,
11781116 #[ serde] args : SpawnArgs ,
11791117) -> Result < SpawnOutput , ProcessError > {
1180- let stdout = matches ! ( args. stdio. stdout, StdioOrFdOrRid :: Stdio ( Stdio :: Piped ) ) ;
1181- let stderr = matches ! ( args. stdio. stderr, StdioOrFdOrRid :: Stdio ( Stdio :: Piped ) ) ;
1118+ let stdout = matches ! ( args. stdio. stdout, StdioOrRid :: Stdio ( Stdio :: Piped ) ) ;
1119+ let stderr = matches ! ( args. stdio. stderr, StdioOrRid :: Stdio ( Stdio :: Piped ) ) ;
11821120 let input = args. input . clone ( ) ;
11831121 let ( mut command, _, _, _) =
11841122 create_command ( state, args, "Deno.Command().outputSync()" ) ?;
@@ -1275,11 +1213,11 @@ mod deprecated {
12751213 cwd : Option < String > ,
12761214 env : Vec < ( String , String ) > ,
12771215 #[ from_v8( serde) ]
1278- stdin : StdioOrFdOrRid ,
1216+ stdin : StdioOrRid ,
12791217 #[ from_v8( serde) ]
1280- stdout : StdioOrFdOrRid ,
1218+ stdout : StdioOrRid ,
12811219 #[ from_v8( serde) ]
1282- stderr : StdioOrFdOrRid ,
1220+ stderr : StdioOrRid ,
12831221 }
12841222
12851223 struct ChildResource {
@@ -1355,14 +1293,14 @@ mod deprecated {
13551293 c. stdin ( run_args. stdin . as_stdio ( state) ?) ;
13561294 c. stdout (
13571295 match run_args. stdout {
1358- StdioOrFdOrRid :: Stdio ( Stdio :: Inherit ) => StdioOrFdOrRid :: Rid ( 1 ) ,
1296+ StdioOrRid :: Stdio ( Stdio :: Inherit ) => StdioOrRid :: Rid ( 1 ) ,
13591297 value => value,
13601298 }
13611299 . as_stdio ( state) ?,
13621300 ) ;
13631301 c. stderr (
13641302 match run_args. stderr {
1365- StdioOrFdOrRid :: Stdio ( Stdio :: Inherit ) => StdioOrFdOrRid :: Rid ( 2 ) ,
1303+ StdioOrRid :: Stdio ( Stdio :: Inherit ) => StdioOrRid :: Rid ( 2 ) ,
13661304 value => value,
13671305 }
13681306 . as_stdio ( state) ?,
0 commit comments