|
| 1 | +diff --git a/lib/src/SharedLibManager.cc b/lib/src/SharedLibManager.cc |
| 2 | +index bf67b4f2..7a035a48 100644 |
| 3 | +--- a/lib/src/SharedLibManager.cc |
| 4 | ++++ b/lib/src/SharedLibManager.cc |
| 5 | +@@ -17,10 +17,49 @@ |
| 6 | + #include <dirent.h> |
| 7 | + #include <dlfcn.h> |
| 8 | + #include <fstream> |
| 9 | ++#include <sstream> |
| 10 | + #include <sys/types.h> |
| 11 | ++#include <sys/wait.h> |
| 12 | + #include <trantor/utils/Logger.h> |
| 13 | + #include <unistd.h> |
| 14 | + |
| 15 | ++// Safe exec helper: runs a program with explicit argv, no shell involved. |
| 16 | ++// Returns the exit status, or -1 on fork/exec failure. |
| 17 | ++static int safeExec(const std::vector<std::string> &args) |
| 18 | ++{ |
| 19 | ++ if (args.empty()) |
| 20 | ++ return -1; |
| 21 | ++ |
| 22 | ++ std::vector<char *> argv; |
| 23 | ++ argv.reserve(args.size() + 1); |
| 24 | ++ for (auto &a : args) |
| 25 | ++ argv.push_back(const_cast<char *>(a.c_str())); |
| 26 | ++ argv.push_back(nullptr); |
| 27 | ++ |
| 28 | ++ pid_t pid = fork(); |
| 29 | ++ if (pid == -1) |
| 30 | ++ { |
| 31 | ++ perror("fork"); |
| 32 | ++ return -1; |
| 33 | ++ } |
| 34 | ++ if (pid == 0) |
| 35 | ++ { |
| 36 | ++ // Child: replace image with the target program. |
| 37 | ++ execvp(argv[0], argv.data()); |
| 38 | ++ // execvp only returns on error. |
| 39 | ++ perror("execvp"); |
| 40 | ++ _exit(127); |
| 41 | ++ } |
| 42 | ++ // Parent: wait for child. |
| 43 | ++ int status = 0; |
| 44 | ++ if (waitpid(pid, &status, 0) == -1) |
| 45 | ++ { |
| 46 | ++ perror("waitpid"); |
| 47 | ++ return -1; |
| 48 | ++ } |
| 49 | ++ return WIFEXITED(status) ? WEXITSTATUS(status) : -1; |
| 50 | ++} |
| 51 | ++ |
| 52 | + static void forEachFileIn( |
| 53 | + const std::string &path, |
| 54 | + const std::function<void(const std::string &, const struct stat &)> &cb) |
| 55 | +@@ -153,20 +192,18 @@ void SharedLibManager::managerLibs() |
| 56 | + else |
| 57 | + { |
| 58 | + // generate source code and compile it. |
| 59 | +- std::string cmd = "drogon_ctl create view "; |
| 60 | +- if (!outputPath_.empty()) |
| 61 | +- { |
| 62 | +- cmd.append(filename).append(" -o ").append( |
| 63 | +- outputPath_); |
| 64 | +- } |
| 65 | +- else |
| 66 | +- { |
| 67 | +- cmd.append(filename).append(" -o ").append( |
| 68 | +- libPath); |
| 69 | +- } |
| 70 | ++ const std::string &outDir = |
| 71 | ++ !outputPath_.empty() ? outputPath_ : libPath; |
| 72 | ++ std::vector<std::string> genArgs = {"drogon_ctl", |
| 73 | ++ "create", |
| 74 | ++ "view", |
| 75 | ++ filename, |
| 76 | ++ "-o", |
| 77 | ++ outDir}; |
| 78 | + srcFile.append(".cc"); |
| 79 | +- LOG_TRACE << cmd; |
| 80 | +- auto r = system(cmd.c_str()); |
| 81 | ++ LOG_TRACE << "drogon_ctl create view " << filename |
| 82 | ++ << " -o " << outDir; |
| 83 | ++ auto r = safeExec(genArgs); |
| 84 | + // TODO: handle r |
| 85 | + (void)(r); |
| 86 | + dlStat.handle = |
| 87 | +@@ -203,24 +240,45 @@ void *SharedLibManager::compileAndLoadLib(const std::string &sourceFile, |
| 88 | + void *oldHld) |
| 89 | + { |
| 90 | + LOG_TRACE << "src:" << sourceFile; |
| 91 | +- std::string cmd = COMPILER_COMMAND; |
| 92 | +- cmd.append(" ") |
| 93 | +- .append(sourceFile) |
| 94 | +- .append(" ") |
| 95 | +- .append(COMPILATION_FLAGS) |
| 96 | +- .append(" ") |
| 97 | +- .append(INCLUDING_DIRS); |
| 98 | +- if (std::string(COMPILER_ID).find("Clang") != std::string::npos) |
| 99 | +- cmd.append(" -shared -fPIC -undefined dynamic_lookup -o "); |
| 100 | +- else |
| 101 | +- cmd.append(" -shared -fPIC --no-gnu-unique -o "); |
| 102 | + auto pos = sourceFile.rfind('.'); |
| 103 | + auto soFile = sourceFile.substr(0, pos); |
| 104 | + soFile.append(".so"); |
| 105 | +- cmd.append(soFile); |
| 106 | +- LOG_TRACE << cmd; |
| 107 | + |
| 108 | +- if (system(cmd.c_str()) == 0) |
| 109 | ++ // Build argv without invoking a shell so that metacharacters in |
| 110 | ++ // sourceFile or soFile cannot be interpreted by /bin/sh. |
| 111 | ++ std::vector<std::string> compileArgs; |
| 112 | ++ compileArgs.push_back(COMPILER_COMMAND); |
| 113 | ++ |
| 114 | ++ // COMPILATION_FLAGS and INCLUDING_DIRS are baked in at build time from |
| 115 | ++ // trusted CMake variables; split them on whitespace into separate tokens. |
| 116 | ++ auto splitIntoArgs = [&](const std::string &s) { |
| 117 | ++ std::istringstream iss(s); |
| 118 | ++ std::string token; |
| 119 | ++ while (iss >> token) |
| 120 | ++ compileArgs.push_back(token); |
| 121 | ++ }; |
| 122 | ++ compileArgs.push_back(sourceFile); |
| 123 | ++ splitIntoArgs(COMPILATION_FLAGS); |
| 124 | ++ splitIntoArgs(INCLUDING_DIRS); |
| 125 | ++ if (std::string(COMPILER_ID).find("Clang") != std::string::npos) |
| 126 | ++ { |
| 127 | ++ compileArgs.push_back("-shared"); |
| 128 | ++ compileArgs.push_back("-fPIC"); |
| 129 | ++ compileArgs.push_back("-undefined"); |
| 130 | ++ compileArgs.push_back("dynamic_lookup"); |
| 131 | ++ } |
| 132 | ++ else |
| 133 | ++ { |
| 134 | ++ compileArgs.push_back("-shared"); |
| 135 | ++ compileArgs.push_back("-fPIC"); |
| 136 | ++ compileArgs.push_back("--no-gnu-unique"); |
| 137 | ++ } |
| 138 | ++ compileArgs.push_back("-o"); |
| 139 | ++ compileArgs.push_back(soFile); |
| 140 | ++ |
| 141 | ++ LOG_TRACE << COMPILER_COMMAND << " " << sourceFile << " ... -o " << soFile; |
| 142 | ++ |
| 143 | ++ if (safeExec(compileArgs) == 0) |
| 144 | + { |
| 145 | + LOG_TRACE << "Compiled successfully:" << soFile; |
| 146 | + return loadLib(soFile, oldHld); |
0 commit comments