|
19 | 19 | #include "xinspect.hpp"
|
20 | 20 | #include "xmagics/os.hpp"
|
21 | 21 | #include <iostream>
|
| 22 | +#include <fcntl.h> |
| 23 | +#include <unistd.h> |
22 | 24 | #ifndef EMSCRIPTEN
|
23 | 25 | #include "xmagics/xassist.hpp"
|
24 | 26 | #endif
|
|
27 | 29 |
|
28 | 30 | using Args = std::vector<const char*>;
|
29 | 31 |
|
| 32 | +static int g_stdin_pipe[2] = {-1, -1}; |
| 33 | +static int g_stdout_pipe[2] = {-1, -1}; |
| 34 | +static int g_stderr_pipe[2] = {-1, -1}; |
| 35 | +static bool g_pipes_initialized = false; |
| 36 | + |
| 37 | +// Initialize global pipes once |
| 38 | +void init_global_pipes() { |
| 39 | + if (!g_pipes_initialized) { |
| 40 | + if (pipe(g_stdin_pipe) == 0 && pipe(g_stdout_pipe) == 0 && pipe(g_stderr_pipe) == 0) { |
| 41 | + g_pipes_initialized = true; |
| 42 | + } else { |
| 43 | + throw std::runtime_error("Failed to create global pipes"); |
| 44 | + } |
| 45 | + } |
| 46 | +} |
| 47 | + |
30 | 48 | void* createInterpreter(const Args& ExtraArgs = {})
|
31 | 49 | {
|
32 | 50 | Args ClangArgs = {/*"-xc++"*/"-v"};
|
@@ -56,13 +74,61 @@ void* createInterpreter(const Args& ExtraArgs = {})
|
56 | 74 | return Cpp::CreateInterpreter(ClangArgs /*, {"-cuda"}*/);
|
57 | 75 | }
|
58 | 76 |
|
59 |
| - return Cpp::CreateInterpreter(ClangArgs, {}, true); |
| 77 | + init_global_pipes(); |
| 78 | + |
| 79 | + return Cpp::CreateInterpreter(ClangArgs, {}, true, g_stdin_pipe[0], g_stdout_pipe[1], g_stderr_pipe[1]); |
60 | 80 | }
|
61 | 81 |
|
62 | 82 | using namespace std::placeholders;
|
63 | 83 |
|
64 | 84 | namespace xcpp
|
65 | 85 | {
|
| 86 | + class GlobalPipeRedirectRAII { |
| 87 | + private: |
| 88 | + std::string captured_stderr; |
| 89 | + |
| 90 | + std::string read_all_from_fd(int fd) { |
| 91 | + std::string result; |
| 92 | + char buffer[4096]; |
| 93 | + ssize_t bytes_read; |
| 94 | + |
| 95 | + // Set non-blocking to avoid hanging |
| 96 | + int flags = fcntl(fd, F_GETFL, 0); |
| 97 | + fcntl(fd, F_SETFL, flags | O_NONBLOCK); |
| 98 | + |
| 99 | + while ((bytes_read = read(fd, buffer, sizeof(buffer))) > 0) { |
| 100 | + result.append(buffer, bytes_read); |
| 101 | + } |
| 102 | + |
| 103 | + // Restore original flags |
| 104 | + fcntl(fd, F_SETFL, flags); |
| 105 | + return result; |
| 106 | + } |
| 107 | + |
| 108 | + void write_to_fd(int fd, const std::string& data) { |
| 109 | + write(fd, data.c_str(), data.length()); |
| 110 | + } |
| 111 | + |
| 112 | + public: |
| 113 | + GlobalPipeRedirectRAII(const std::string& input_data = "") { |
| 114 | + if (!input_data.empty() && g_stdin_pipe[1] != -1) { |
| 115 | + write_to_fd(g_stdin_pipe[1], input_data); |
| 116 | + close(g_stdin_pipe[1]); // Close write end to signal EOF |
| 117 | + } |
| 118 | + } |
| 119 | + ~GlobalPipeRedirectRAII() { |
| 120 | + // Read any pending output from pipes |
| 121 | + std::string stdout_content = read_all_from_fd(g_stdout_pipe[0]); |
| 122 | + captured_stderr = read_all_from_fd(g_stderr_pipe[0]); |
| 123 | + |
| 124 | + // Output captured stdout content |
| 125 | + if (!stdout_content.empty()) { |
| 126 | + std::cout << stdout_content; |
| 127 | + } |
| 128 | + } |
| 129 | + |
| 130 | + const std::string& get_captured_stderr() const { return captured_stderr; } |
| 131 | + }; |
66 | 132 | struct StreamRedirectRAII {
|
67 | 133 | std::string &err;
|
68 | 134 | StreamRedirectRAII(std::string &e) : err(e) {
|
@@ -180,11 +246,20 @@ __get_cxx_version ()
|
180 | 246 | m_code_to_execution_count_map[code].push_back(execution_count);
|
181 | 247 | m_execution_count_to_code_map[execution_count] = code;
|
182 | 248 |
|
| 249 | + bool use_out_of_process = g_pipes_initialized; |
| 250 | + |
183 | 251 | // Attempt normal evaluation
|
184 | 252 | try
|
185 | 253 | {
|
186 |
| - StreamRedirectRAII R(err); |
187 |
| - compilation_result = Cpp::Process(code.c_str()); |
| 254 | + if (use_out_of_process) { |
| 255 | + std::string input_for_process = ""; |
| 256 | + GlobalPipeRedirectRAII redirect(input_for_process); |
| 257 | + compilation_result = Cpp::Process(code.c_str()); |
| 258 | + err = redirect.get_captured_stderr(); |
| 259 | + } else { |
| 260 | + StreamRedirectRAII R(err); |
| 261 | + compilation_result = Cpp::Process(code.c_str()); |
| 262 | + } |
188 | 263 | }
|
189 | 264 | catch (std::exception& e)
|
190 | 265 | {
|
|
0 commit comments