Skip to content

Commit 5bf0fa0

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

File tree

3 files changed

+41
-87
lines changed

3 files changed

+41
-87
lines changed

compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp

Lines changed: 22 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -281,53 +281,39 @@ 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[], pid_t* pid,
285+
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
287+
// this can 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)
299+
return false;
317300

318301
auto acts_cleanup = at_scope_exit([&] {
319302
posix_spawn_file_actions_destroy(&acts);
320303
});
321304

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;
305+
res = posix_spawn_file_actions_adddup2(&acts, fd_stdin, STDIN_FILENO) ||
306+
posix_spawn_file_actions_adddup2(&acts, fd_stdout, STDOUT_FILENO) ||
307+
posix_spawn_file_actions_addclose(&acts, fd_stdin) ||
308+
posix_spawn_file_actions_addclose(&acts, fd_stdout);
309+
if (res != 0)
310+
return false;
326311

327312
// Spawn attributes
328313
posix_spawnattr_t attrs;
329314
res = posix_spawnattr_init(&attrs);
330-
if (res != 0) return kInvalidFd;
315+
if (res != 0)
316+
return false;
331317

332318
auto attrs_cleanup = at_scope_exit([&] {
333319
posix_spawnattr_destroy(&attrs);
@@ -336,50 +322,17 @@ static fd_t internal_spawn_impl(const char *argv[], const char *envp[],
336322
// In the spawned process, close all file descriptors that are not explicitly
337323
// described by the file actions object. This is Darwin-specific extension.
338324
res = posix_spawnattr_setflags(&attrs, POSIX_SPAWN_CLOEXEC_DEFAULT);
339-
if (res != 0) return kInvalidFd;
325+
if (res != 0)
326+
return false;
340327

341328
// posix_spawn
342329
char **argv_casted = const_cast<char **>(argv);
343330
char **envp_casted = const_cast<char **>(envp);
344331
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);
377-
378-
for (; count > 0; count--) {
379-
internal_close(low_fds[count]);
380-
}
332+
if (res != 0)
333+
return false;
381334

382-
return fd;
335+
return true;
383336
}
384337

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

compiler-rt/lib/sanitizer_common/sanitizer_posix.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ 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,
71+
fd_t stdin, fd_t stdout);
7172

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

compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cpp

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -156,42 +156,42 @@ 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()),
171+
&pid, outfd[0], infd[1]);
172+
if (!success) {
163173
Report("WARNING: failed to spawn external symbolizer (errno: %d)\n",
164174
errno);
175+
internal_close(infd[0]);
176+
internal_close(outfd[1]);
165177
return false;
166178
}
167-
168-
input_fd_ = fd;
169-
output_fd_ = fd;
170179
# else // SANITIZER_APPLE
171180
UNIMPLEMENTED();
172181
# endif // SANITIZER_APPLE
173182
} 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-
183183
pid = StartSubprocess(path_, argv, GetEnvP(), /* stdin */ outfd[0],
184184
/* stdout */ infd[1]);
185185
if (pid < 0) {
186186
internal_close(infd[0]);
187187
internal_close(outfd[1]);
188188
return false;
189189
}
190-
191-
input_fd_ = infd[0];
192-
output_fd_ = outfd[1];
193190
}
194191

192+
input_fd_ = infd[0];
193+
output_fd_ = outfd[1];
194+
195195
CHECK_GT(pid, 0);
196196

197197
// Check that symbolizer subprocess started successfully.

0 commit comments

Comments
 (0)