@@ -52,30 +52,45 @@ impl Command {
5252 None => ptr:: null ( ) ,
5353 } ;
5454
55- let make_action = |local_io : & ChildStdio , target_fd| if let Some ( local_fd) = local_io. fd ( ) {
56- fdio_spawn_action_t {
57- action : FDIO_SPAWN_ACTION_TRANSFER_FD ,
58- local_fd,
59- target_fd,
60- ..Default :: default ( )
61- }
62- } else {
63- if let ChildStdio :: Null = local_io {
64- // acts as no-op
65- return Default :: default ( ) ;
66- }
67- fdio_spawn_action_t {
68- action : FDIO_SPAWN_ACTION_CLONE_FD ,
69- local_fd : target_fd,
70- target_fd,
71- ..Default :: default ( )
55+ let make_action = |local_io : & ChildStdio , target_fd| -> io:: Result < fdio_spawn_action_t > {
56+ if let Some ( local_fd) = local_io. fd ( ) {
57+ Ok ( fdio_spawn_action_t {
58+ action : FDIO_SPAWN_ACTION_TRANSFER_FD ,
59+ local_fd,
60+ target_fd,
61+ ..Default :: default ( )
62+ } )
63+ } else {
64+ if let ChildStdio :: Null = local_io {
65+ // acts as no-op
66+ return Ok ( Default :: default ( ) ) ;
67+ }
68+
69+ let mut handle = ZX_HANDLE_INVALID ;
70+ let status = fdio_fd_clone ( target_fd, & mut handle) ;
71+ if status == ERR_INVALID_ARGS || status == ERR_NOT_SUPPORTED {
72+ // This descriptor is closed; skip it rather than generating an
73+ // error.
74+ return Ok ( Default :: default ( ) ) ;
75+ }
76+ zx_cvt ( status) ?;
77+
78+ let mut cloned_fd = 0 ;
79+ zx_cvt ( fdio_fd_create ( handle, & mut cloned_fd) ) ?;
80+
81+ Ok ( fdio_spawn_action_t {
82+ action : FDIO_SPAWN_ACTION_TRANSFER_FD ,
83+ local_fd : cloned_fd as i32 ,
84+ target_fd,
85+ ..Default :: default ( )
86+ } )
7287 }
7388 } ;
7489
7590 // Clone stdin, stdout, and stderr
76- let action1 = make_action ( & stdio. stdin , 0 ) ;
77- let action2 = make_action ( & stdio. stdout , 1 ) ;
78- let action3 = make_action ( & stdio. stderr , 2 ) ;
91+ let action1 = make_action ( & stdio. stdin , 0 ) ? ;
92+ let action2 = make_action ( & stdio. stdout , 1 ) ? ;
93+ let action3 = make_action ( & stdio. stderr , 2 ) ? ;
7994 let actions = [ action1, action2, action3] ;
8095
8196 // We don't want FileDesc::drop to be called on any stdio. fdio_spawn_etc
@@ -88,7 +103,7 @@ impl Command {
88103
89104 let mut process_handle: zx_handle_t = 0 ;
90105 zx_cvt ( fdio_spawn_etc (
91- 0 ,
106+ ZX_HANDLE_INVALID ,
92107 FDIO_SPAWN_CLONE_JOB | FDIO_SPAWN_CLONE_LDSVC | FDIO_SPAWN_CLONE_NAMESPACE ,
93108 self . get_argv ( ) [ 0 ] , self . get_argv ( ) . as_ptr ( ) , envp,
94109 actions. len ( ) as size_t , actions. as_ptr ( ) ,
0 commit comments