@@ -48,30 +48,51 @@ impl Command {
48
48
use crate :: sys:: process:: zircon:: * ;
49
49
50
50
let envp = match maybe_envp {
51
- Some ( envp) => envp. as_ptr ( ) ,
51
+ // None means to clone the current environment, which is done in the
52
+ // flags below.
52
53
None => ptr:: null ( ) ,
54
+ Some ( envp) => envp. as_ptr ( ) ,
53
55
} ;
54
56
55
- let transfer_or_clone = |opt_fd, target_fd| if let Some ( local_fd) = opt_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
- fdio_spawn_action_t {
64
- action : FDIO_SPAWN_ACTION_CLONE_FD ,
65
- local_fd : target_fd,
66
- target_fd,
67
- ..Default :: default ( )
57
+ let make_action = |local_io : & ChildStdio , target_fd| -> io:: Result < fdio_spawn_action_t > {
58
+ if let Some ( local_fd) = local_io. fd ( ) {
59
+ Ok ( fdio_spawn_action_t {
60
+ action : FDIO_SPAWN_ACTION_TRANSFER_FD ,
61
+ local_fd,
62
+ target_fd,
63
+ ..Default :: default ( )
64
+ } )
65
+ } else {
66
+ if let ChildStdio :: Null = local_io {
67
+ // acts as no-op
68
+ return Ok ( Default :: default ( ) ) ;
69
+ }
70
+
71
+ let mut handle = ZX_HANDLE_INVALID ;
72
+ let status = fdio_fd_clone ( target_fd, & mut handle) ;
73
+ if status == ERR_INVALID_ARGS || status == ERR_NOT_SUPPORTED {
74
+ // This descriptor is closed; skip it rather than generating an
75
+ // error.
76
+ return Ok ( Default :: default ( ) ) ;
77
+ }
78
+ zx_cvt ( status) ?;
79
+
80
+ let mut cloned_fd = 0 ;
81
+ zx_cvt ( fdio_fd_create ( handle, & mut cloned_fd) ) ?;
82
+
83
+ Ok ( fdio_spawn_action_t {
84
+ action : FDIO_SPAWN_ACTION_TRANSFER_FD ,
85
+ local_fd : cloned_fd as i32 ,
86
+ target_fd,
87
+ ..Default :: default ( )
88
+ } )
68
89
}
69
90
} ;
70
91
71
92
// Clone stdin, stdout, and stderr
72
- let action1 = transfer_or_clone ( stdio. stdin . fd ( ) , 0 ) ;
73
- let action2 = transfer_or_clone ( stdio. stdout . fd ( ) , 1 ) ;
74
- let action3 = transfer_or_clone ( stdio. stderr . fd ( ) , 2 ) ;
93
+ let action1 = make_action ( & stdio. stdin , 0 ) ? ;
94
+ let action2 = make_action ( & stdio. stdout , 1 ) ? ;
95
+ let action3 = make_action ( & stdio. stderr , 2 ) ? ;
75
96
let actions = [ action1, action2, action3] ;
76
97
77
98
// We don't want FileDesc::drop to be called on any stdio. fdio_spawn_etc
@@ -84,9 +105,11 @@ impl Command {
84
105
85
106
let mut process_handle: zx_handle_t = 0 ;
86
107
zx_cvt ( fdio_spawn_etc (
87
- 0 ,
88
- FDIO_SPAWN_CLONE_JOB | FDIO_SPAWN_CLONE_LDSVC | FDIO_SPAWN_CLONE_NAMESPACE ,
89
- self . get_argv ( ) [ 0 ] , self . get_argv ( ) . as_ptr ( ) , envp, 3 , actions. as_ptr ( ) ,
108
+ ZX_HANDLE_INVALID ,
109
+ FDIO_SPAWN_CLONE_JOB | FDIO_SPAWN_CLONE_LDSVC | FDIO_SPAWN_CLONE_NAMESPACE
110
+ | FDIO_SPAWN_CLONE_ENVIRON , // this is ignored when envp is non-null
111
+ self . get_argv ( ) [ 0 ] , self . get_argv ( ) . as_ptr ( ) , envp,
112
+ actions. len ( ) as size_t , actions. as_ptr ( ) ,
90
113
& mut process_handle,
91
114
ptr:: null_mut ( ) ,
92
115
) ) ?;
0 commit comments