From e891c29f9bc6aec94db80d44ed8c24d4142f7c3f Mon Sep 17 00:00:00 2001 From: Josh Haberman Date: Wed, 30 Dec 2015 16:03:49 -0800 Subject: Allow conformance test runner to tolerate crashes, and re-enable conformance tests. --- conformance/conformance_test_runner.cc | 64 ++++++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 11 deletions(-) (limited to 'conformance/conformance_test_runner.cc') diff --git a/conformance/conformance_test_runner.cc b/conformance/conformance_test_runner.cc index f2b0dabf..376a60b9 100644 --- a/conformance/conformance_test_runner.cc +++ b/conformance/conformance_test_runner.cc @@ -55,16 +55,21 @@ #include #include -#include #include +#include +#include +#include #include +#include + #include "conformance.pb.h" #include "conformance_test.h" using conformance::ConformanceRequest; using conformance::ConformanceResponse; using google::protobuf::internal::scoped_array; +using google::protobuf::StringAppendF; using std::string; using std::vector; @@ -81,14 +86,14 @@ using std::vector; class ForkPipeRunner : public google::protobuf::ConformanceTestRunner { public: ForkPipeRunner(const std::string &executable) - : running_(false), executable_(executable) {} + : child_pid_(-1), executable_(executable) {} virtual ~ForkPipeRunner() {} void RunTest(const std::string& test_name, const std::string& request, std::string* response) { - if (!running_) { + if (child_pid_ < 0) { SpawnTestProgram(); } @@ -97,7 +102,31 @@ class ForkPipeRunner : public google::protobuf::ConformanceTestRunner { uint32_t len = request.size(); CheckedWrite(write_fd_, &len, sizeof(uint32_t)); CheckedWrite(write_fd_, request.c_str(), request.size()); - CheckedRead(read_fd_, &len, sizeof(uint32_t)); + + if (!TryRead(read_fd_, &len, sizeof(uint32_t))) { + // We failed to read from the child, assume a crash and try to reap. + GOOGLE_LOG(INFO) << "Trying to reap child, pid=" << child_pid_; + + int status; + waitpid(child_pid_, &status, WEXITED); + + string error_msg; + if (WIFEXITED(status)) { + StringAppendF(&error_msg, + "child exited, status=%d", WEXITSTATUS(status)); + } else if (WIFSIGNALED(status)) { + StringAppendF(&error_msg, + "child killed by signal %d", WTERMSIG(status)); + } + GOOGLE_LOG(INFO) << error_msg; + child_pid_ = -1; + + conformance::ConformanceResponse response_obj; + response_obj.set_runtime_error(error_msg); + response_obj.SerializeToString(response); + return; + } + response->resize(len); CheckedRead(read_fd_, (void*)response->c_str(), len); } @@ -141,7 +170,7 @@ class ForkPipeRunner : public google::protobuf::ConformanceTestRunner { CHECK_SYSCALL(close(fromproc_pipe_fd[1])); write_fd_ = toproc_pipe_fd[1]; read_fd_ = fromproc_pipe_fd[0]; - running_ = true; + child_pid_ = pid; } else { // Child. CHECK_SYSCALL(close(STDIN_FILENO)); @@ -171,28 +200,40 @@ class ForkPipeRunner : public google::protobuf::ConformanceTestRunner { } } - void CheckedRead(int fd, void *buf, size_t len) { + bool TryRead(int fd, void *buf, size_t len) { size_t ofs = 0; while (len > 0) { ssize_t bytes_read = read(fd, (char*)buf + ofs, len); if (bytes_read == 0) { - GOOGLE_LOG(FATAL) << current_test_name_ + GOOGLE_LOG(ERROR) << current_test_name_ << ": unexpected EOF from test program"; + return false; } else if (bytes_read < 0) { - GOOGLE_LOG(FATAL) << current_test_name_ + GOOGLE_LOG(ERROR) << current_test_name_ << ": error reading from test program: " << strerror(errno); + return false; } len -= bytes_read; ofs += bytes_read; } + + return true; + } + + void CheckedRead(int fd, void *buf, size_t len) { + if (!TryRead(fd, buf, len)) { + GOOGLE_LOG(FATAL) << current_test_name_ + << ": error reading from test program: " + << strerror(errno); + } } int write_fd_; int read_fd_; - bool running_; + pid_t child_pid_; std::string executable_; std::string current_test_name_; }; @@ -239,12 +280,12 @@ int main(int argc, char *argv[]) { char *program; google::protobuf::ConformanceTestSuite suite; + vector failure_list; + for (int arg = 1; arg < argc; ++arg) { if (strcmp(argv[arg], "--failure_list") == 0) { if (++arg == argc) UsageError(); - vector failure_list; ParseFailureList(argv[arg], &failure_list); - suite.SetFailureList(failure_list); } else if (strcmp(argv[arg], "--verbose") == 0) { suite.SetVerbose(true); } else if (argv[arg][0] == '-') { @@ -259,6 +300,7 @@ int main(int argc, char *argv[]) { } } + suite.SetFailureList(failure_list); ForkPipeRunner runner(program); std::string output; -- cgit v1.2.3