1*71db0c75SAndroid Build Coastguard Worker //===-- ExecuteFunction implementation for Unix-like Systems --------------===//
2*71db0c75SAndroid Build Coastguard Worker //
3*71db0c75SAndroid Build Coastguard Worker // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*71db0c75SAndroid Build Coastguard Worker // See https://llvm.org/LICENSE.txt for license information.
5*71db0c75SAndroid Build Coastguard Worker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*71db0c75SAndroid Build Coastguard Worker //
7*71db0c75SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
8*71db0c75SAndroid Build Coastguard Worker
9*71db0c75SAndroid Build Coastguard Worker #include "ExecuteFunction.h"
10*71db0c75SAndroid Build Coastguard Worker #include "src/__support/macros/config.h"
11*71db0c75SAndroid Build Coastguard Worker #include <cassert>
12*71db0c75SAndroid Build Coastguard Worker #include <cstdlib>
13*71db0c75SAndroid Build Coastguard Worker #include <cstring>
14*71db0c75SAndroid Build Coastguard Worker #include <iostream>
15*71db0c75SAndroid Build Coastguard Worker #include <memory>
16*71db0c75SAndroid Build Coastguard Worker #include <poll.h>
17*71db0c75SAndroid Build Coastguard Worker #include <signal.h>
18*71db0c75SAndroid Build Coastguard Worker #include <sys/wait.h>
19*71db0c75SAndroid Build Coastguard Worker #include <unistd.h>
20*71db0c75SAndroid Build Coastguard Worker
21*71db0c75SAndroid Build Coastguard Worker namespace LIBC_NAMESPACE_DECL {
22*71db0c75SAndroid Build Coastguard Worker namespace testutils {
23*71db0c75SAndroid Build Coastguard Worker
exited_normally()24*71db0c75SAndroid Build Coastguard Worker bool ProcessStatus::exited_normally() { return WIFEXITED(platform_defined); }
25*71db0c75SAndroid Build Coastguard Worker
get_exit_code()26*71db0c75SAndroid Build Coastguard Worker int ProcessStatus::get_exit_code() {
27*71db0c75SAndroid Build Coastguard Worker assert(exited_normally() && "Abnormal termination, no exit code");
28*71db0c75SAndroid Build Coastguard Worker return WEXITSTATUS(platform_defined);
29*71db0c75SAndroid Build Coastguard Worker }
30*71db0c75SAndroid Build Coastguard Worker
get_fatal_signal()31*71db0c75SAndroid Build Coastguard Worker int ProcessStatus::get_fatal_signal() {
32*71db0c75SAndroid Build Coastguard Worker if (exited_normally())
33*71db0c75SAndroid Build Coastguard Worker return 0;
34*71db0c75SAndroid Build Coastguard Worker return WTERMSIG(platform_defined);
35*71db0c75SAndroid Build Coastguard Worker }
36*71db0c75SAndroid Build Coastguard Worker
invoke_in_subprocess(FunctionCaller * func,unsigned timeout_ms)37*71db0c75SAndroid Build Coastguard Worker ProcessStatus invoke_in_subprocess(FunctionCaller *func, unsigned timeout_ms) {
38*71db0c75SAndroid Build Coastguard Worker std::unique_ptr<FunctionCaller> X(func);
39*71db0c75SAndroid Build Coastguard Worker int pipe_fds[2];
40*71db0c75SAndroid Build Coastguard Worker if (::pipe(pipe_fds) == -1)
41*71db0c75SAndroid Build Coastguard Worker return ProcessStatus::error("pipe(2) failed");
42*71db0c75SAndroid Build Coastguard Worker
43*71db0c75SAndroid Build Coastguard Worker // Don't copy the buffers into the child process and print twice.
44*71db0c75SAndroid Build Coastguard Worker std::cout.flush();
45*71db0c75SAndroid Build Coastguard Worker std::cerr.flush();
46*71db0c75SAndroid Build Coastguard Worker pid_t pid = ::fork();
47*71db0c75SAndroid Build Coastguard Worker if (pid == -1)
48*71db0c75SAndroid Build Coastguard Worker return ProcessStatus::error("fork(2) failed");
49*71db0c75SAndroid Build Coastguard Worker
50*71db0c75SAndroid Build Coastguard Worker if (!pid) {
51*71db0c75SAndroid Build Coastguard Worker (*func)();
52*71db0c75SAndroid Build Coastguard Worker std::exit(0);
53*71db0c75SAndroid Build Coastguard Worker }
54*71db0c75SAndroid Build Coastguard Worker ::close(pipe_fds[1]);
55*71db0c75SAndroid Build Coastguard Worker
56*71db0c75SAndroid Build Coastguard Worker struct pollfd poll_fd {
57*71db0c75SAndroid Build Coastguard Worker pipe_fds[0], 0, 0
58*71db0c75SAndroid Build Coastguard Worker };
59*71db0c75SAndroid Build Coastguard Worker // No events requested so this call will only return after the timeout or if
60*71db0c75SAndroid Build Coastguard Worker // the pipes peer was closed, signaling the process exited.
61*71db0c75SAndroid Build Coastguard Worker if (::poll(&poll_fd, 1, timeout_ms) == -1)
62*71db0c75SAndroid Build Coastguard Worker return ProcessStatus::error("poll(2) failed");
63*71db0c75SAndroid Build Coastguard Worker // If the pipe wasn't closed by the child yet then timeout has expired.
64*71db0c75SAndroid Build Coastguard Worker if (!(poll_fd.revents & POLLHUP)) {
65*71db0c75SAndroid Build Coastguard Worker ::kill(pid, SIGKILL);
66*71db0c75SAndroid Build Coastguard Worker return ProcessStatus::timed_out_ps();
67*71db0c75SAndroid Build Coastguard Worker }
68*71db0c75SAndroid Build Coastguard Worker
69*71db0c75SAndroid Build Coastguard Worker int wstatus = 0;
70*71db0c75SAndroid Build Coastguard Worker // Wait on the pid of the subprocess here so it gets collected by the system
71*71db0c75SAndroid Build Coastguard Worker // and doesn't turn into a zombie.
72*71db0c75SAndroid Build Coastguard Worker pid_t status = ::waitpid(pid, &wstatus, 0);
73*71db0c75SAndroid Build Coastguard Worker if (status == -1)
74*71db0c75SAndroid Build Coastguard Worker return ProcessStatus::error("waitpid(2) failed");
75*71db0c75SAndroid Build Coastguard Worker assert(status == pid);
76*71db0c75SAndroid Build Coastguard Worker return {wstatus};
77*71db0c75SAndroid Build Coastguard Worker }
78*71db0c75SAndroid Build Coastguard Worker
signal_as_string(int signum)79*71db0c75SAndroid Build Coastguard Worker const char *signal_as_string(int signum) { return ::strsignal(signum); }
80*71db0c75SAndroid Build Coastguard Worker
81*71db0c75SAndroid Build Coastguard Worker } // namespace testutils
82*71db0c75SAndroid Build Coastguard Worker } // namespace LIBC_NAMESPACE_DECL
83