19 #if defined(OPENSSL_LINUX) && !defined(OPENSSL_TSAN)
28 #if defined(OPENSSL_THREADS)
33 #include <gtest/gtest.h>
38 static pid_t WaitpidEINTR(pid_t pid,
int *out_status,
int options) {
42 }
while (
ret < 0 && errno == EINTR);
50 static void CheckGenerationInChild(
const char *
name,
uint64_t expected) {
52 if (generation != expected) {
53 fprintf(
stderr,
"%s generation (#1) was %" PRIu64
", wanted %" PRIu64
".\n",
54 name, generation, expected);
60 if (generation != expected) {
61 fprintf(
stderr,
"%s generation (#2) was %" PRIu64
", wanted %" PRIu64
".\n",
62 name, generation, expected);
72 const pid_t pid = fork();
76 }
else if (pid == 0) {
83 if (WaitpidEINTR(pid, &
status, 0) < 0) {
88 fprintf(
stderr,
"Child did not exit cleanly.\n");
91 if (WEXITSTATUS(
status) != 0) {
93 _exit(WEXITSTATUS(
status));
100 fprintf(
stderr,
"Fork detection not supported. Skipping test.\n");
108 const pid_t
child = fork();
113 for (
int i = 0;
i < 2;
i++) {
114 ForkInChild([&] { CheckGenerationInChild(
"Grandchild",
start + 1); });
119 CheckGenerationInChild(
"Child",
start + 1);
122 for (
int i = 0;
i < 2;
i++) {
123 ForkInChild([&] { CheckGenerationInChild(
"Grandchild",
start + 2); });
126 #if defined(OPENSSL_THREADS)
131 std::vector<std::thread>
threads(4);
132 for (
int i = 0;
i < 2;
i++) {
135 [&] { CheckGenerationInChild(
"Grandchild thread",
start + 2); });
142 #endif // OPENSSL_THREADS
145 CheckGenerationInChild(
"Child",
start + 1);
152 <<
"Error in waitpid: " << strerror(errno);
160 #endif // OPENSSL_LINUX && !OPENSSL_TSAN