summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sandbox/linux/tests/unit_tests.cc44
1 files changed, 44 insertions, 0 deletions
diff --git a/sandbox/linux/tests/unit_tests.cc b/sandbox/linux/tests/unit_tests.cc
index e770bf5..9973b75 100644
--- a/sandbox/linux/tests/unit_tests.cc
+++ b/sandbox/linux/tests/unit_tests.cc
@@ -2,11 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <fcntl.h>
+#include <signal.h>
#include <stdio.h>
#include <sys/resource.h>
#include <sys/time.h>
+#include <unistd.h>
#include "base/file_util.h"
+#include "base/third_party/valgrind/valgrind.h"
#include "sandbox/linux/tests/unit_tests.h"
namespace {
@@ -20,6 +24,40 @@ namespace sandbox {
static const int kExpectedValue = 42;
static const int kIgnoreThisTest = 43;
static const int kExitWithAssertionFailure = 1;
+static const int kExitForTimeout = 2;
+
+static void SigAlrmHandler(int) {
+ const char failure_message[] = "Timeout reached!\n";
+ // Make sure that we never block here.
+ if (!fcntl(2, F_SETFL, O_NONBLOCK)) {
+ if (write(2, failure_message, sizeof(failure_message) - 1) < 0) {
+ }
+ }
+ _exit(kExitForTimeout);
+}
+
+// Set a timeout with a handler that will automatically fail the
+// test.
+static void SetProcessTimeout(int time_in_seconds) {
+ struct sigaction act = {};
+ act.sa_handler = SigAlrmHandler;
+ SANDBOX_ASSERT(sigemptyset(&act.sa_mask) == 0);
+ act.sa_flags = 0;
+
+ struct sigaction old_act;
+ SANDBOX_ASSERT(sigaction(SIGALRM, &act, &old_act) == 0);
+
+ // We don't implemenet signal chaining, so make sure that nothing else
+ // is expecting to handle SIGALRM.
+ SANDBOX_ASSERT((old_act.sa_flags & SA_SIGINFO) == 0);
+ SANDBOX_ASSERT(old_act.sa_handler == SIG_DFL);
+ sigset_t sigalrm_set;
+ SANDBOX_ASSERT(sigemptyset(&sigalrm_set) == 0);
+ SANDBOX_ASSERT(sigaddset(&sigalrm_set, SIGALRM) == 0);
+ SANDBOX_ASSERT(sigprocmask(SIG_UNBLOCK, &sigalrm_set, NULL) == 0);
+ SANDBOX_ASSERT(alarm(time_in_seconds) == 0); // There should be no previous
+ // alarm.
+}
void UnitTests::RunTestInProcess(UnitTests::Test test, void *arg,
DeathCheck death, const void *death_aux) {
@@ -40,6 +78,12 @@ void UnitTests::RunTestInProcess(UnitTests::Test test, void *arg,
SANDBOX_ASSERT(!close(fds[0]));
SANDBOX_ASSERT(!close(fds[1]));
+ // Don't set a timeout if running on Valgrind, since it's generally much
+ // slower.
+ if (!RUNNING_ON_VALGRIND) {
+ SetProcessTimeout(10 /* seconds */);
+ }
+
// Disable core files. They are not very useful for our individual test
// cases.
struct rlimit no_core = { 0 };