X-Git-Url: https://git.ucc.asn.au/?p=progcomp2012.git;a=blobdiff_plain;f=judge%2Fmanager%2Fprogram.cpp;h=5ea1591611a6dbab3f631a3018c978a4e4c4ef1c;hp=d5463f4073a71a3f13fefdbbc85e1ffd2c87cc5e;hb=9daf6066a0a00f4682a4047d7504d044306c6084;hpb=e1153eebe8cfd0c881cef2ff8fca63f130e736b3 diff --git a/judge/manager/program.cpp b/judge/manager/program.cpp index d5463f4..5ea1591 100644 --- a/judge/manager/program.cpp +++ b/judge/manager/program.cpp @@ -6,6 +6,14 @@ #include "thread_util.h" #include "program.h" +#include +#include +#include + +#include +#include +#include +#include using namespace std; @@ -20,8 +28,48 @@ using namespace std; * The child process closes unused sides of the pipe, and then calls exec to replace itself with the AI program * The parent process closes unused sides of the pipe, and sets up member variables - associates streams with the pipe fd's for convenience. */ -Program::Program(const char * executablePath) : input(NULL), output(NULL), pid(0) +Program::Program(const char * executablePath) : input(NULL), output(NULL), pid(0), paused(false) { + + + + vector args; + if (executablePath[0] != '"') + args.push_back((char*)executablePath); + else + args.push_back((char*)(executablePath)+1); + char * token = NULL; + do + { + token = strstr(args[args.size()-1], " "); + if (token == NULL) + break; + + *token = '\0'; + do + { + ++token; + if (*token == '"') + *token = '\0'; + } + while (*token != '\0' && iswspace(*token)); + + if (*token != '\0' && !iswspace(*token)) + { + args.push_back(token); + } + else + break; + } + while (token != NULL); + + char ** arguments = NULL; + if (args.size() > 0) + { + arguments = new char*[args.size()]; + for (unsigned int i=0; i < args.size(); ++i) + arguments[i] = args[i]; + } //See if file exists and is executable... if (access(executablePath, X_OK) != 0) { @@ -51,8 +99,10 @@ Program::Program(const char * executablePath) : input(NULL), output(NULL), pid(0 if (access(executablePath, X_OK) == 0) //Check we STILL have permissions to start the file - execl(executablePath, executablePath, (char*)(NULL)); ///Replace process with desired executable - + { + execv(executablePath,arguments); ///Replace process with desired executable + } + perror("execv error:\n"); fprintf(stderr, "Program::Program - Could not run program \"%s\"!\n", executablePath); exit(EXIT_FAILURE); //We will probably have to terminate the whole program if this happens } @@ -100,8 +150,42 @@ Program::~Program() } +/** + * Forces the program to pause by sending SIGSTOP + * Program can be resumed by calling Continue() (which sends SIGCONT) + * @returns true if the program could be paused, false if it couldn't (probably because it wasn't running) + */ +bool Program::Pause() +{ + if (pid > 0 && kill(pid,SIGSTOP) == 0) + { + paused = true; + return true; + } + return false; +} +/** + * Causes a paused program to continue + * @returns true if the program could be continued, false if it couldn't (probably because it wasn't running) + */ +bool Program::Continue() +{ + if (pid > 0 && kill(pid,SIGCONT) == 0) + { + paused = false; + return true; + } + return false; +} +/** + * @returns true iff the program is paused + */ +bool Program::Paused() const +{ + return paused; +} /** @@ -143,6 +227,31 @@ bool Program::GetMessage(string & buffer, double timeout) if (!Running() || timeout == 0) return false; + struct timeval tv; + fd_set readfds; + + tv.tv_sec = (int)(timeout); + tv.tv_usec = (timeout - (double)((int)timeout)) * 1000000; + + int fd = fileno(input); + + FD_ZERO(&readfds); + FD_SET(fd, &readfds); + + select(fd+1, &readfds, NULL, NULL, &tv); + + if (!FD_ISSET(fd, &readfds)) + return false; //Timed out + //fprintf(stderr, "Got message!\n"); + for (char c = fgetc(input); c != '\n' && (int)(c) != EOF; c = fgetc(input)) + { + //fprintf(stderr, "%c", c); + buffer += c; + } + //fprintf(stderr, "%s\n", buffer.c_str()); + return true; + + /* Old way, using threads, which apparently is terrible assert(&buffer != NULL); GetterThread getterThread(input, buffer); assert(&(getterThread.buffer) != NULL); @@ -173,7 +282,7 @@ bool Program::GetMessage(string & buffer, double timeout) if (buffer.size() == 1 && buffer[0] == EOF) return false; return true; - + */ }