mirror of
https://github.com/intel/llvm.git
synced 2026-01-15 12:25:46 +08:00
[libc] [UnitTest] Add timeout to death tests
Summary: This patch adds a timeout of 500ms to death tests. As we add multithreaded code and locks, deadlocks become more likely so timeout will be useful. Additionally: - Better error handling in `invokeSubprocess` - Makes `ProcessStatus`'s methods const Reviewers: sivachandra, MaskRay, gchatelet, PaulkaToast Reviewed By: sivachandra, PaulkaToast Subscribers: tschuett, libc-commits Differential Revision: https://reviews.llvm.org/D75651
This commit is contained in:
@@ -10,6 +10,8 @@
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
@@ -17,32 +19,57 @@
|
||||
namespace __llvm_libc {
|
||||
namespace testutils {
|
||||
|
||||
bool ProcessStatus::exitedNormally() { return WIFEXITED(PlatformDefined); }
|
||||
bool ProcessStatus::exitedNormally() const {
|
||||
return WIFEXITED(PlatformDefined);
|
||||
}
|
||||
|
||||
int ProcessStatus::getExitCode() {
|
||||
int ProcessStatus::getExitCode() const {
|
||||
assert(exitedNormally() && "Abnormal termination, no exit code");
|
||||
return WEXITSTATUS(PlatformDefined);
|
||||
}
|
||||
|
||||
int ProcessStatus::getFatalSignal() {
|
||||
int ProcessStatus::getFatalSignal() const {
|
||||
if (exitedNormally())
|
||||
return 0;
|
||||
return WTERMSIG(PlatformDefined);
|
||||
}
|
||||
|
||||
ProcessStatus invokeInSubprocess(FunctionCaller *Func) {
|
||||
ProcessStatus invokeInSubprocess(FunctionCaller *Func, unsigned timeoutMS) {
|
||||
std::unique_ptr<FunctionCaller> X(Func);
|
||||
int pipeFDs[2];
|
||||
if (::pipe(pipeFDs) == -1)
|
||||
return ProcessStatus::Error("pipe(2) failed");
|
||||
|
||||
// Don't copy the buffers into the child process and print twice.
|
||||
llvm::outs().flush();
|
||||
llvm::errs().flush();
|
||||
pid_t Pid = ::fork();
|
||||
if (Pid == -1)
|
||||
return ProcessStatus::Error("fork(2) failed");
|
||||
|
||||
if (!Pid) {
|
||||
(*Func)();
|
||||
std::exit(0);
|
||||
}
|
||||
::close(pipeFDs[1]);
|
||||
|
||||
int WStatus;
|
||||
::waitpid(Pid, &WStatus, 0);
|
||||
delete Func;
|
||||
struct pollfd pollFD {
|
||||
pipeFDs[0], 0, 0
|
||||
};
|
||||
// No events requested so this call will only return after the timeout or if
|
||||
// the pipes peer was closed, signaling the process exited.
|
||||
if (::poll(&pollFD, 1, timeoutMS) == -1)
|
||||
return ProcessStatus::Error("poll(2) failed");
|
||||
// If the pipe wasn't closed by the child yet then timeout has expired.
|
||||
if (!(pollFD.revents & POLLHUP)) {
|
||||
::kill(Pid, SIGKILL);
|
||||
return ProcessStatus::TimedOut();
|
||||
}
|
||||
|
||||
int WStatus = 0;
|
||||
int status = ::waitpid(Pid, &WStatus, WNOHANG);
|
||||
assert(status == Pid && "wait call should not block here");
|
||||
(void)status;
|
||||
return {WStatus};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user