X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=manager%2Fprogram.cpp;h=c936de38d42cc23830d838d770b9da0a7388bb81;hb=HEAD;hp=acf501e25b94e5f07b0142515897ee2d619629c0;hpb=b563784f7e8b559fc100e174331c99fc6a1beda8;p=progcomp2012.git diff --git a/manager/program.cpp b/manager/program.cpp deleted file mode 100644 index acf501e..0000000 --- a/manager/program.cpp +++ /dev/null @@ -1,172 +0,0 @@ -#include - -#include - -#include - -#include "thread_util.h" -#include "program.h" - - -using namespace std; - - -/** - * Constructor - * @param executablePath - path to the program that will be run - * - * Creates two pipes - one for each direction between the parent process and the AI program - * Forks the process. - * 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) -{ - - - int readPipe[2]; int writePipe[2]; - assert(pipe(readPipe) == 0); - assert(pipe(writePipe) == 0); - - pid = fork(); - if (pid == 0) - { - close(readPipe[0]); //close end that parent reads from - close(writePipe[1]); //close end that parent writes to - - //TODO: Fix possible bug here if the process is already a daemon - assert(writePipe[0] != 0 && readPipe[1] != 1); - dup2(writePipe[0],0); close(writePipe[0]); //pipe end child reads from goes to STDIN - dup2(readPipe[1], 1); close(readPipe[1]); //pipe end child writes to goes to STDOUT - - //TODO: Somehow force the exec'd process to be unbuffered - setbuf(stdin, NULL); //WARNING: These lines don't appear to have any affect - setbuf(stdout, NULL); //You should add them at the start of the wrapped program. - //If your wrapped program is not written in C/C++, you will probably have a problem - - - - execl(executablePath, executablePath, (char*)(NULL)); ///Replace process with desired executable - 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 - } - else - { - close(writePipe[0]); //close end that child writes to - close(readPipe[1]); //close end that child reads from - - input = fdopen(readPipe[0],"r"); output = fdopen(writePipe[1],"w"); - setbuf(input, NULL); - setbuf(output, NULL); - } - -} - -/** - * Destructor - * Writes EOF to the wrapped program and then closes all streams - * Kills the wrapped program if it does not exit within 1 second. - */ -Program::~Program() -{ - if (kill(pid, 0) == 0) //Check if the process created is still running... - { - fputc(EOF, output); //If it was, tell it to stop with EOF - usleep(500000); //Give it 1/2 a second to respond... - if (kill(pid, 0) == 0) //Check if its still running - { - kill(pid, 9); //Slay the infidel mercilessly! - } - } - fclose(input); - fclose(output); - -} - - - - - -/** - * Sends a message to the wrapped AI program - * WARNING: Always prints a new line after the message (so don't include a new line) - * This is because everything is always line buffered. - * @returns true if the message was successfully sent; false if it was not (ie: the process was not running!) - */ -bool Program::SendMessage(const char * print, ...) -{ - if (kill(pid, 0) != 0) //Is the process running... - return false; - - va_list ap; - va_start(ap, print); - - if (vfprintf(output, print, ap) < 0 || fprintf(output, "\n") < 0) - { - va_end(ap); - return false; - } - va_end(ap); - - - - - return true; -} - - -/** - * Retrieves a message from the wrapped AI program, waiting a maximum amount of time - * @param buffer - C++ string to store the resultant message in - * @param timeout - Maximum amount of time to wait before failure. If timeout <= 0, then GetMessage will wait indefinately. - * @returns true if the response was recieved within the specified time, false if it was not, or an EOF was recieved, or the process was not running. - */ -bool Program::GetMessage(string & buffer, double timeout) -{ - if (kill(pid, 0) != 0) - return false; - - assert(&buffer != NULL); - GetterThread getterThread(input, buffer); - assert(&(getterThread.buffer) != NULL); - TimerThread timerThread(timeout*1000000); - - getterThread.Start(); - if (timeout > 0) - timerThread.Start(); - - - while (!getterThread.Finished()) - { - if (timeout > 0 && timerThread.Finished()) - { - getterThread.Stop(); - timerThread.Stop(); - return false; - } - } - - getterThread.Stop(); - timerThread.Stop(); - - - - if (buffer.size() == 1 && buffer[0] == EOF) - return false; - return true; - - -} - -/** - * Returns true iff the process is running - * @returns what I just said, fool - */ -bool Program::Running() const -{ - return (kill(pid,0) == 0); -} - - - -