void DeathTestImpl::_doTest() { #ifdef _WIN32 log() << "Skipping death test on Windows"; return; #else int pipes[2]; checkSyscall(pipe(pipes)); pid_t child; checkSyscall(child = fork()); if (child) { checkSyscall(close(pipes[1])); char buf[1000]; std::ostringstream os; ssize_t bytesRead; while (0 < (bytesRead = read(pipes[0], buf, sizeof(buf)))) { os.write(buf, bytesRead); invariant(os); } checkSyscall(bytesRead); pid_t pid; int stat; while (child != (pid = waitpid(child, &stat, 0))) { invariant(pid == -1); const int err = errno; switch (err) { case EINTR: continue; default: severe() << "Unrecoverable error while waiting for " << child << ": " << errnoWithDescription(err); MONGO_UNREACHABLE; } } if (WIFSIGNALED(stat) || (WIFEXITED(stat) && WEXITSTATUS(stat) != 0)) { // Exited with a signal or non-zero code. Should check the pattern, here, // but haven't figured out how, so just return. ASSERT_STRING_CONTAINS(os.str(), getPattern()); return; } else { invariant(!WIFSTOPPED(stat)); } FAIL("Expected death, found life\n\n") << os.str(); } // This code only executes in the child process. checkSyscall(close(pipes[0])); checkSyscall(dup2(pipes[1], 1)); checkSyscall(dup2(1, 2)); try { _test->run(); } catch (const TestAssertionFailureException& tafe) { log() << "Caught test exception while expecting death: " << tafe; // To fail the test, we must exit with a successful error code, because the parent process // is checking for the child to die with an exit code indicating an error. quickExit(EXIT_SUCCESS); } quickExit(EXIT_SUCCESS); #endif }
int main(int argc, char *argv[]) { int tdcount, tlimit, mlimit; char exename[1024], inputfile[1024]; struct rlimit r; if (argc < 6) { printf("Usage: [id] [probid] [input] [time limit] [memory limit]\n"); exit(RET_SE); } tlimit = atoi(argv[4]); mlimit = atoi(argv[5]); sprintf(exename, "./%s", argv[1]); strcpy(inputfile, argv[3]); if ((pid = fork()) == 0) { freopen("input.txt", "r", stdin); chdir("sandbox"); chroot("."); freopen("output.txt", "w", stdout); setregid(99, 99); setreuid(99, 99); ptrace(PTRACE_TRACEME, 0, NULL, NULL); execl(exename, exename, NULL); exit(0); } signal(SIGALRM, timer); alarm(1); int stat, tmpmem, sig; for (;;) { wait4(pid, &stat, 0, &rinfo); if (WIFEXITED(stat)) { puts("exited!\n"); break; } else if (WIFSTOPPED(stat)) { sig = WSTOPSIG(stat); if (sig == SIGTRAP) { if (checkSyscall() == RET_RF) { ptrace(PTRACE_KILL, pid, NULL, NULL); final_result(RET_RF); } } else if (sig == SIGUSR1) { } else printf("Stopped due to signal: %d\n", sig); } else if (WIFSIGNALED(stat)) { //Runtime Error printf("Runtime Error. Received signal: %d\n", WTERMSIG(stat)); final_result(RET_RE); break; } tmpmem = getMemory(); if (tmpmem > maxmem) maxmem = tmpmem; if (maxmem > mlimit) final_result(RET_MLE); if (getRuntime() > tlimit) { ptrace(PTRACE_KILL, pid, NULL, NULL); final_result(RET_TLE); } ptrace(PTRACE_SYSCALL, pid, NULL, NULL); } final_result(RET_AC); return 0; }