From 2a02d4bee3f683180a40b65a2c3833ceb64236c3 Mon Sep 17 00:00:00 2001 From: Alp Toker Date: Thu, 23 Jan 2014 22:19:45 +0000 Subject: lli: Factor portable messaging into a new RPCChannel facility The client and server now use a single unified low-level RPC core built around LLVM's existing cross-platform abstractions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@199947 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/lli/Unix/RPCChannel.inc | 118 ++++++++++++++++++++++++++++ tools/lli/Unix/RemoteTargetExternal.inc | 133 -------------------------------- 2 files changed, 118 insertions(+), 133 deletions(-) create mode 100644 tools/lli/Unix/RPCChannel.inc delete mode 100644 tools/lli/Unix/RemoteTargetExternal.inc (limited to 'tools/lli/Unix') diff --git a/tools/lli/Unix/RPCChannel.inc b/tools/lli/Unix/RPCChannel.inc new file mode 100644 index 0000000000..b7dec37d93 --- /dev/null +++ b/tools/lli/Unix/RPCChannel.inc @@ -0,0 +1,118 @@ +//=- RPCChannel.inc - LLVM out-of-process JIT execution for Unix --=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implementation of the Unix-specific parts of the RPCChannel class +// which executes JITed code in a separate process from where it was built. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include +#include + +namespace { + +struct ConnectionData_t { + int InputPipe; + int OutputPipe; + + ConnectionData_t(int in, int out) : InputPipe(in), OutputPipe(out) {} +}; + +} // namespace + +namespace llvm { + +bool RPCChannel::createServer() { + int PipeFD[2][2]; + pid_t ChildPID; + + // Create two pipes. + if (pipe(PipeFD[0]) != 0 || pipe(PipeFD[1]) != 0) + perror("Error creating pipe: "); + + ChildPID = fork(); + + if (ChildPID == 0) { + // In the child... + + // Close the parent ends of the pipes + close(PipeFD[0][1]); + close(PipeFD[1][0]); + + // Use our pipes as stdin and stdout + if (PipeFD[0][0] != STDIN_FILENO) { + dup2(PipeFD[0][0], STDIN_FILENO); + close(PipeFD[0][0]); + } + if (PipeFD[1][1] != STDOUT_FILENO) { + dup2(PipeFD[1][1], STDOUT_FILENO); + close(PipeFD[1][1]); + } + + // Execute the child process. + char *args[1] = { NULL }; + int rc = execv(ChildName.c_str(), args); + if (rc != 0) + perror("Error executing child process: "); + } else { + // In the parent... + + // Close the child ends of the pipes + close(PipeFD[0][0]); + close(PipeFD[1][1]); + + // Store the parent ends of the pipes + ConnectionData = (void *)new ConnectionData_t(PipeFD[1][0], PipeFD[0][1]); + return true; + } + return false; +} + +bool RPCChannel::createClient() { + // Store the parent ends of the pipes + ConnectionData = (void *)new ConnectionData_t(STDIN_FILENO, STDOUT_FILENO); + return true; +} + +void RPCChannel::ReportError(int rc, size_t Size, std::string &ErrorMsg) { + if (rc == -1) { + if (errno == EPIPE) + ErrorMsg += "pipe closed"; + else if (errno == EINTR) + ErrorMsg += "interrupted"; + else + ErrorMsg += "file descriptor error"; + } else { + char Number[10] = { 0 }; + ErrorMsg += "Expecting "; + sprintf(Number, "%d", (uint32_t)Size); + ErrorMsg += Number; + ErrorMsg += " bytes, Got "; + sprintf(Number, "%d", rc); + ErrorMsg += Number; + } +} + +int RPCChannel::WriteBytes(const void *Data, size_t Size) { + return write(((ConnectionData_t *)ConnectionData)->OutputPipe, Data, Size); +} + +int RPCChannel::ReadBytes(void *Data, size_t Size) { + return read(((ConnectionData_t *)ConnectionData)->InputPipe, Data, Size); +} + +void RPCChannel::Wait() { wait(NULL); } + +RPCChannel::~RPCChannel() { + delete static_cast(ConnectionData); +} + +} // namespace llvm diff --git a/tools/lli/Unix/RemoteTargetExternal.inc b/tools/lli/Unix/RemoteTargetExternal.inc deleted file mode 100644 index ea8e4597d5..0000000000 --- a/tools/lli/Unix/RemoteTargetExternal.inc +++ /dev/null @@ -1,133 +0,0 @@ -//=- RemoteTargetExternal.inc - LLVM out-of-process JIT execution for Unix --=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Implementation of the Unix-specific parts of the RemoteTargetExternal class -// which executes JITed code in a separate process from where it was built. -// -//===----------------------------------------------------------------------===// - -#include -#include -#include -#include - -namespace { - -struct ConnectionData_t { - int InputPipe; - int OutputPipe; - - ConnectionData_t(int in, int out) : InputPipe(in), OutputPipe(out) {} -}; - -} // namespace - -namespace llvm { - -bool RemoteTargetExternal::create() { - int PipeFD[2][2]; - pid_t ChildPID; - - // Create two pipes. - if (pipe(PipeFD[0]) != 0 || pipe(PipeFD[1]) != 0) - perror("Error creating pipe: "); - - ChildPID = fork(); - - if (ChildPID == 0) { - // In the child... - - // Close the parent ends of the pipes - close(PipeFD[0][1]); - close(PipeFD[1][0]); - - // Use our pipes as stdin and stdout - if (PipeFD[0][0] != STDIN_FILENO) { - dup2(PipeFD[0][0], STDIN_FILENO); - close(PipeFD[0][0]); - } - if (PipeFD[1][1] != STDOUT_FILENO) { - dup2(PipeFD[1][1], STDOUT_FILENO); - close(PipeFD[1][1]); - } - - // Execute the child process. - char *args[1] = { NULL }; - int rc = execv(ChildName.c_str(), args); - if (rc != 0) - perror("Error executing child process: "); - } - else { - // In the parent... - - // Close the child ends of the pipes - close(PipeFD[0][0]); - close(PipeFD[1][1]); - - // Store the parent ends of the pipes - ConnectionData = (void*)new ConnectionData_t(PipeFD[1][0], PipeFD[0][1]); - - // We must get Ack from the client (blocking read) - if (!Receive(LLI_ChildActive)) { - ErrorMsg += ", (RemoteTargetExternal::create) - Stopping process!"; - stop(); - return false; - } - } - return true; -} - -static void ReportError(int rc, size_t Size, std::string &ErrorMsg) { - if (rc == -1) { - if (errno == EPIPE) - ErrorMsg += "pipe closed"; - else if (errno == EINTR) - ErrorMsg += "interrupted"; - else - ErrorMsg += "file descriptor error"; - } else { - char Number[10] = { 0 }; - ErrorMsg += "Expecting "; - sprintf(Number, "%d", (uint32_t)Size); - ErrorMsg += Number; - ErrorMsg += " bytes, Got "; - sprintf(Number, "%d", rc); - ErrorMsg += Number; - } -} - -bool RemoteTargetExternal::WriteBytes(const void *Data, size_t Size) { - int rc = write(((ConnectionData_t*)ConnectionData)->OutputPipe, Data, Size); - if (rc != -1 && (size_t)rc == Size) - return true; - - ErrorMsg = "WriteBytes: "; - ReportError(rc, Size, ErrorMsg); - return false; -} - -bool RemoteTargetExternal::ReadBytes(void *Data, size_t Size) { - int rc = read(((ConnectionData_t*)ConnectionData)->InputPipe, Data, Size); - if (rc != -1 && (size_t)rc == Size) - return true; - - ErrorMsg = "ReadBytes: "; - ReportError(rc, Size, ErrorMsg); - return false; -} - -void RemoteTargetExternal::Wait() { - wait(NULL); -} - -RemoteTargetExternal::~RemoteTargetExternal() { - delete static_cast(ConnectionData); -} - -} // namespace llvm -- cgit v1.2.3