Skip to content

Commit 5ab3a13

Browse files
author
kr-2003
committed
redirection handle
1 parent 290becd commit 5ab3a13

File tree

1 file changed

+78
-3
lines changed

1 file changed

+78
-3
lines changed

src/xinterpreter.cpp

Lines changed: 78 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#include "xinspect.hpp"
2020
#include "xmagics/os.hpp"
2121
#include <iostream>
22+
#include <fcntl.h>
23+
#include <unistd.h>
2224
#ifndef EMSCRIPTEN
2325
#include "xmagics/xassist.hpp"
2426
#endif
@@ -27,6 +29,22 @@
2729

2830
using Args = std::vector<const char*>;
2931

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+
3048
void* createInterpreter(const Args& ExtraArgs = {})
3149
{
3250
Args ClangArgs = {/*"-xc++"*/"-v"};
@@ -56,13 +74,61 @@ void* createInterpreter(const Args& ExtraArgs = {})
5674
return Cpp::CreateInterpreter(ClangArgs /*, {"-cuda"}*/);
5775
}
5876

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]);
6080
}
6181

6282
using namespace std::placeholders;
6383

6484
namespace xcpp
6585
{
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+
};
66132
struct StreamRedirectRAII {
67133
std::string &err;
68134
StreamRedirectRAII(std::string &e) : err(e) {
@@ -180,11 +246,20 @@ __get_cxx_version ()
180246
m_code_to_execution_count_map[code].push_back(execution_count);
181247
m_execution_count_to_code_map[execution_count] = code;
182248

249+
bool use_out_of_process = g_pipes_initialized;
250+
183251
// Attempt normal evaluation
184252
try
185253
{
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+
}
188263
}
189264
catch (std::exception& e)
190265
{

0 commit comments

Comments
 (0)