@@ -281,53 +281,36 @@ int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp,
281281 (size_t )newlen);
282282}
283283
284- static fd_t internal_spawn_impl (const char *argv[], const char *envp[],
285- pid_t *pid) {
286- fd_t primary_fd = kInvalidFd ;
287- fd_t secondary_fd = kInvalidFd ;
284+ bool internal_spawn (const char *argv[], const char *envp[],
285+ pid_t *pid, fd_t fd_stdin, fd_t fd_stdout ) {
286+ // NOTE: Caller ensures that fd_stdin and fd_stdout are not 0, 1, or 2, since this can
287+ // break communication.
288288
289+ int res;
289290 auto fd_closer = at_scope_exit ([&] {
290- internal_close (primary_fd );
291- internal_close (secondary_fd );
291+ internal_close (fd_stdin );
292+ internal_close (fd_stdout );
292293 });
293294
294- // We need a new pseudoterminal to avoid buffering problems. The 'atos' tool
295- // in particular detects when it's talking to a pipe and forgets to flush the
296- // output stream after sending a response.
297- primary_fd = posix_openpt (O_RDWR);
298- if (primary_fd == kInvalidFd )
299- return kInvalidFd ;
300-
301- int res = grantpt (primary_fd) || unlockpt (primary_fd);
302- if (res != 0 ) return kInvalidFd ;
303-
304- // Use TIOCPTYGNAME instead of ptsname() to avoid threading problems.
305- char secondary_pty_name[128 ];
306- res = ioctl (primary_fd, TIOCPTYGNAME, secondary_pty_name);
307- if (res == -1 ) return kInvalidFd ;
308-
309- secondary_fd = internal_open (secondary_pty_name, O_RDWR);
310- if (secondary_fd == kInvalidFd )
311- return kInvalidFd ;
312-
313295 // File descriptor actions
314296 posix_spawn_file_actions_t acts;
315297 res = posix_spawn_file_actions_init (&acts);
316- if (res != 0 ) return kInvalidFd ;
298+ if (res != 0 ) return false ;
317299
318300 auto acts_cleanup = at_scope_exit ([&] {
319301 posix_spawn_file_actions_destroy (&acts);
320302 });
321303
322- res = posix_spawn_file_actions_adddup2 (&acts, secondary_fd, STDIN_FILENO) ||
323- posix_spawn_file_actions_adddup2 (&acts, secondary_fd, STDOUT_FILENO) ||
324- posix_spawn_file_actions_addclose (&acts, secondary_fd);
325- if (res != 0 ) return kInvalidFd ;
304+ res = posix_spawn_file_actions_adddup2 (&acts, fd_stdin, STDIN_FILENO) ||
305+ posix_spawn_file_actions_adddup2 (&acts, fd_stdout, STDOUT_FILENO) ||
306+ posix_spawn_file_actions_addclose (&acts, fd_stdin) ||
307+ posix_spawn_file_actions_addclose (&acts, fd_stdout);
308+ if (res != 0 ) return false ;
326309
327310 // Spawn attributes
328311 posix_spawnattr_t attrs;
329312 res = posix_spawnattr_init (&attrs);
330- if (res != 0 ) return kInvalidFd ;
313+ if (res != 0 ) return false ;
331314
332315 auto attrs_cleanup = at_scope_exit ([&] {
333316 posix_spawnattr_destroy (&attrs);
@@ -336,50 +319,15 @@ static fd_t internal_spawn_impl(const char *argv[], const char *envp[],
336319 // In the spawned process, close all file descriptors that are not explicitly
337320 // described by the file actions object. This is Darwin-specific extension.
338321 res = posix_spawnattr_setflags (&attrs, POSIX_SPAWN_CLOEXEC_DEFAULT);
339- if (res != 0 ) return kInvalidFd ;
322+ if (res != 0 ) return false ;
340323
341324 // posix_spawn
342325 char **argv_casted = const_cast <char **>(argv);
343326 char **envp_casted = const_cast <char **>(envp);
344327 res = posix_spawn (pid, argv[0 ], &acts, &attrs, argv_casted, envp_casted);
345- if (res != 0 ) return kInvalidFd ;
346-
347- // Disable echo in the new terminal, disable CR.
348- struct termios termflags;
349- tcgetattr (primary_fd, &termflags);
350- termflags.c_oflag &= ~ONLCR;
351- termflags.c_lflag &= ~ECHO;
352- tcsetattr (primary_fd, TCSANOW, &termflags);
353-
354- // On success, do not close primary_fd on scope exit.
355- fd_t fd = primary_fd;
356- primary_fd = kInvalidFd ;
357-
358- return fd;
359- }
360-
361- fd_t internal_spawn (const char *argv[], const char *envp[], pid_t *pid) {
362- // The client program may close its stdin and/or stdout and/or stderr thus
363- // allowing open/posix_openpt to reuse file descriptors 0, 1 or 2. In this
364- // case the communication is broken if either the parent or the child tries to
365- // close or duplicate these descriptors. We temporarily reserve these
366- // descriptors here to prevent this.
367- fd_t low_fds[3 ];
368- size_t count = 0 ;
369-
370- for (; count < 3 ; count++) {
371- low_fds[count] = posix_openpt (O_RDWR);
372- if (low_fds[count] >= STDERR_FILENO)
373- break ;
374- }
375-
376- fd_t fd = internal_spawn_impl (argv, envp, pid);
328+ if (res != 0 ) return false ;
377329
378- for (; count > 0 ; count--) {
379- internal_close (low_fds[count]);
380- }
381-
382- return fd;
330+ return true ;
383331}
384332
385333uptr internal_rename (const char *oldpath, const char *newpath) {
0 commit comments