We have some x-platform code to launch a sub-process with a comm channel using openpty() and posix_spawn(). Overview: 1) openpty() to get a master/slave pair, 2) turn off ECHO and ICANON on the slave fd, 3) posix_spawn_file dup2 the slave to stdin, stderr, and stdout, 4) posix_spawn the command, 5) cleanup in master, including close() for the slave. On FreeBSD 10.0 x86-64 the slave close() will hang, the same code works on Linux (kernel 3.x) and OSX (10.6+).
For our automated tests we are just launching a shell script that does
Anyone have any ideas as to what might be going on?
Here are the relevant sections of this function:
For our automated tests we are just launching a shell script that does
Code:
#!/usr/bin/env sh; echo hello world
Anyone have any ideas as to what might be going on?
Here are the relevant sections of this function:
Code:
#define belog(fmt, ...) fprintf(stderr, fmt "\n", ## __VA_ARGS__)
if (-1 == openpty(&master, &slave, NULL, NULL, NULL)) {
belog("%s: openpty failed: %s", __FUNCTION__, strerror(errno));
return (errno);
}
// Child: We don't want input buffering, or to echo our parent's characters.
if (0 == tcgetattr(slave, &tio)) {
tio.c_lflag &= ~ECHO;
if (0 == (flags & kdLaunchBuffered))
tio.c_lflag &= ~ICANON;
else {
#if DEBUG
belog("%s: buffering pty input", __FUNCTION__);
#endif
tio.c_lflag |= ICANON;
}
(void)tcsetattr(slave, TCSANOW|TCSAFLUSH, &tio);
} else {
belog("%s: failed to get child terminal attrs: %s", __FUNCTION__, strerror(errno));
}
// set the pty slave descriptor as the child's std I/O
if (0 == serr)
serr = posix_spawn_file_actions_adddup2(&actions, slave, STDIN_FILENO);
if (0 == serr)
serr = posix_spawn_file_actions_adddup2(&actions, slave, STDOUT_FILENO);
if (0 == serr)
serr = posix_spawn_file_actions_adddup2(&actions, slave, STDERR_FILENO);
PSASSERT(slave > STDERR_FILENO, "why?");
if (0 == serr && slave > STDERR_FILENO)
serr = posix_spawn_file_actions_addclose(&actions, slave);
if (0 != serr) {
belog("%s: posix_spawn_file_actions failed: %s", __FUNCTION__, strerror(errno));
}
Code:
posix_spawnattr_t attrs;
serr = posix_spawnattr_init(&attrs);
if (PS_EXPECTED(0 == serr)) {
extern char **environ;
serr = posix_spawn(&pid, path, &actions, &attrs, argv, environ);
}
(void)close(slave);
(void)posix_spawn_file_actions_destroy(&actions);
(void)posix_spawnattr_destroy(&attrs);