Skip to content

Commit f1678fc

Browse files
committed
Replace pty with pipe in macOS posix_spawn path
1 parent 834b8b7 commit f1678fc

File tree

3 files changed

+34
-87
lines changed

3 files changed

+34
-87
lines changed

compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp

Lines changed: 17 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -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

385333
uptr internal_rename(const char *oldpath, const char *newpath) {

compiler-rt/lib/sanitizer_common/sanitizer_posix.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ uptr internal_ptrace(int request, int pid, void *addr, void *data);
6767
uptr internal_waitpid(int pid, int *status, int options);
6868

6969
int internal_fork();
70-
fd_t internal_spawn(const char *argv[], const char *envp[], pid_t *pid);
70+
bool internal_spawn(const char *argv[], const char *envp[], pid_t *pid, fd_t stdin, fd_t stdout);
7171

7272
int internal_sysctl(const int *name, unsigned int namelen, void *oldp,
7373
uptr *oldlenp, const void *newp, uptr newlen);

compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -156,42 +156,41 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() {
156156
Printf("\n");
157157
}
158158

159+
fd_t infd[2] = {}, outfd[2] = {};
160+
if (!CreateTwoHighNumberedPipes(infd, outfd)) {
161+
Report(
162+
"WARNING: Can't create a socket pair to start "
163+
"external symbolizer (errno: %d)\n",
164+
errno);
165+
return false;
166+
}
167+
159168
if (use_posix_spawn_) {
160169
# if SANITIZER_APPLE
161-
fd_t fd = internal_spawn(argv, const_cast<const char **>(GetEnvP()), &pid);
162-
if (fd == kInvalidFd) {
170+
bool success = internal_spawn(argv, const_cast<const char **>(GetEnvP()), &pid, outfd[0], infd[1]);
171+
if (!success) {
163172
Report("WARNING: failed to spawn external symbolizer (errno: %d)\n",
164173
errno);
174+
internal_close(infd[0]);
175+
internal_close(outfd[1]);
165176
return false;
166177
}
167-
168-
input_fd_ = fd;
169-
output_fd_ = fd;
170178
# else // SANITIZER_APPLE
171179
UNIMPLEMENTED();
172180
# endif // SANITIZER_APPLE
173181
} else {
174-
fd_t infd[2] = {}, outfd[2] = {};
175-
if (!CreateTwoHighNumberedPipes(infd, outfd)) {
176-
Report(
177-
"WARNING: Can't create a socket pair to start "
178-
"external symbolizer (errno: %d)\n",
179-
errno);
180-
return false;
181-
}
182-
183182
pid = StartSubprocess(path_, argv, GetEnvP(), /* stdin */ outfd[0],
184183
/* stdout */ infd[1]);
185184
if (pid < 0) {
186185
internal_close(infd[0]);
187186
internal_close(outfd[1]);
188187
return false;
189188
}
190-
191-
input_fd_ = infd[0];
192-
output_fd_ = outfd[1];
193189
}
194190

191+
input_fd_ = infd[0];
192+
output_fd_ = outfd[1];
193+
195194
CHECK_GT(pid, 0);
196195

197196
// Check that symbolizer subprocess started successfully.

0 commit comments

Comments
 (0)