//===----------------------------------------------------------------------===//
#define _POSIX_MAPPED_FILES
-#include "Support/SystemUtils.h"
-#include "Config/fcntl.h"
-#include "Config/pagesize.h"
-#include "Config/unistd.h"
-#include "Config/windows.h"
-#include "Config/sys/mman.h"
-#include "Config/sys/stat.h"
-#include "Config/sys/types.h"
-#include "Config/sys/wait.h"
+#include "llvm/Support/SystemUtils.h"
+#include "llvm/Config/fcntl.h"
+#include "llvm/Config/pagesize.h"
+#include "llvm/Config/unistd.h"
+#include "llvm/Config/windows.h"
+#include "llvm/Config/sys/mman.h"
+#include "llvm/Config/sys/stat.h"
+#include "llvm/Config/sys/types.h"
+#include "llvm/Config/sys/wait.h"
#include <algorithm>
#include <cerrno>
#include <cstdlib>
#include <fstream>
#include <iostream>
+#include <signal.h>
using namespace llvm;
/// isExecutableFile - This function returns true if the filename specified
close(InFD); // Close the original FD
}
+static bool Timeout = false;
+static void TimeOutHandler(int Sig) {
+ Timeout = true;
+}
+
/// RunProgramWithTimeout - This function executes the specified program, with
/// the specified null-terminated argument array, with the stdin/out/err fd's
-/// redirected, with a timeout specified on the command line. This terminates
+/// redirected, with a timeout specified by the last argument. This terminates
/// the calling program if there is an error executing the specified program.
/// It returns the return value of the program, or -1 if a timeout is detected.
///
const char **Args,
const std::string &StdInFile,
const std::string &StdOutFile,
- const std::string &StdErrFile) {
- // FIXME: install sigalarm handler here for timeout...
-
+ const std::string &StdErrFile,
+ unsigned NumSeconds) {
#ifdef HAVE_SYS_WAIT_H
int Child = fork();
switch (Child) {
// Make sure all output has been written while waiting
std::cout << std::flush;
+ // Install a timeout handler.
+ Timeout = false;
+ struct sigaction Act, Old;
+ Act.sa_sigaction = 0;
+ Act.sa_handler = TimeOutHandler;
+ sigemptyset(&Act.sa_mask);
+ Act.sa_flags = 0;
+ sigaction(SIGALRM, &Act, &Old);
+
+ // Set the timeout if one is set.
+ if (NumSeconds)
+ alarm(NumSeconds);
+
int Status;
- if (wait(&Status) != Child) {
+ while (wait(&Status) != Child)
if (errno == EINTR) {
- static bool FirstTimeout = true;
- if (FirstTimeout) {
- std::cout <<
- "*** Program execution timed out! This mechanism is designed to handle\n"
- " programs stuck in infinite loops gracefully. The -timeout option\n"
- " can be used to change the timeout threshold or disable it completely\n"
- " (with -timeout=0). This message is only displayed once.\n";
- FirstTimeout = false;
+ if (Timeout) {
+ // Kill the child.
+ kill(Child, SIGKILL);
+
+ if (wait(&Status) != Child)
+ std::cerr << "Something funny happened waiting for the child!\n";
+
+ alarm(0);
+ sigaction(SIGALRM, &Old, 0);
+ return -1; // Timeout detected
+ } else {
+ std::cerr << "Error waiting for child process!\n";
+ exit(1);
}
- return -1; // Timeout detected
}
- std::cerr << "Error waiting for child process!\n";
- exit(1);
- }
+ alarm(0);
+ sigaction(SIGALRM, &Old, 0);
return Status;
#else