-
Notifications
You must be signed in to change notification settings - Fork 15.1k
Open
Labels
Description
Running the EXPECT_EXIT macro (by running _Exit_test for example) on darwin (macos) causes
the test to suspend for a while and later timeout.
The likely cause of this is in the file
ExecuteFunctionUnix.cpp.
The poll struct is populated with a zero .event field. This is fine on linux
but hangs on macos. To test this in isolation, here's a small indepent snippet
recreating the condition just like the invoke_in_subprocess fucntion:
#include <assert.h>
#include <errno.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
int main() {
int pipe_fds[2];
if (pipe(pipe_fds) == -1) {
perror("pipe failed");
return EXIT_FAILURE;
}
pid_t pid = fork();
if (pid == -1) {
perror("fork failed");
close(pipe_fds[0]);
close(pipe_fds[1]);
return EXIT_FAILURE;
}
if (pid == 0) {
// child
close(pipe_fds[0]); // Close read end
// Short delay to ensure the parent has time to enter poll()
usleep(100000); // 100ms
printf("Child process exiting, closing pipe write end...\n");
close(pipe_fds[1]);
_exit(0);
}
// Parent
close(pipe_fds[1]); // Close write end in parent
printf("Parent process (PID: %d): Waiting for child (PID: %d) exit via "
"poll(2) for 5000ms...\n",
getpid(), pid);
// LIKELY CAUSE OF ERROR
// Chage .events to POLLIN and it should work
struct pollfd poll_fd = {.fd = pipe_fds[0], .events = 0, .revents = 0};
int timeout_ms = 5000;
int ret = poll(&poll_fd, 1, timeout_ms);
if (ret == -1) {
printf("POLL RESULT: FAILED (-1). errno: %d (%s)\n", errno,
strerror(errno));
} else if (ret == 0) {
printf("POLL RESULT: TIMED OUT (0).\n");
} else {
printf(
"POLL RESULT: SUCCEEDED (%d). revents: 0x%x (Expected POLLHUP 0x%x)\n",
ret, poll_fd.revents, POLLHUP);
assert(poll_fd.revents & POLLHUP);
}
close(pipe_fds[0]);
int wstatus;
if (waitpid(pid, &wstatus, 0) == -1) {
perror("waitpid failed");
}
printf("Parent process finished.\n");
return 0;
}
Compile this and run: clang file.c -o a; ./a. It hangs and exits via a
timeout. Change the events to be POLLIN and it should succeed.
I couldn't find why this happens precisely. My gut feeling is that macos just
doesn't like an empty events field.