You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-04 12:00:25 +00:00
Implement OS.execute_with_pipe method to run process with redirected stdio.
Implement `pipe://*` path handling for creation of named pipes.
This commit is contained in:
@@ -37,6 +37,7 @@
|
||||
#include "core/debugger/script_debugger.h"
|
||||
#include "drivers/unix/dir_access_unix.h"
|
||||
#include "drivers/unix/file_access_unix.h"
|
||||
#include "drivers/unix/file_access_unix_pipe.h"
|
||||
#include "drivers/unix/net_socket_posix.h"
|
||||
#include "drivers/unix/thread_posix.h"
|
||||
#include "servers/rendering_server.h"
|
||||
@@ -160,6 +161,7 @@ void OS_Unix::initialize_core() {
|
||||
FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_RESOURCES);
|
||||
FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_USERDATA);
|
||||
FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_FILESYSTEM);
|
||||
FileAccess::make_default<FileAccessUnixPipe>(FileAccess::ACCESS_PIPE);
|
||||
DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_RESOURCES);
|
||||
DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_USERDATA);
|
||||
DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_FILESYSTEM);
|
||||
@@ -489,6 +491,106 @@ Dictionary OS_Unix::get_memory_info() const {
|
||||
return meminfo;
|
||||
}
|
||||
|
||||
Dictionary OS_Unix::execute_with_pipe(const String &p_path, const List<String> &p_arguments) {
|
||||
#define CLEAN_PIPES \
|
||||
if (pipe_in[0] >= 0) { \
|
||||
::close(pipe_in[0]); \
|
||||
} \
|
||||
if (pipe_in[1] >= 0) { \
|
||||
::close(pipe_in[1]); \
|
||||
} \
|
||||
if (pipe_out[0] >= 0) { \
|
||||
::close(pipe_out[0]); \
|
||||
} \
|
||||
if (pipe_out[1] >= 0) { \
|
||||
::close(pipe_out[1]); \
|
||||
} \
|
||||
if (pipe_err[0] >= 0) { \
|
||||
::close(pipe_err[0]); \
|
||||
} \
|
||||
if (pipe_err[1] >= 0) { \
|
||||
::close(pipe_err[1]); \
|
||||
}
|
||||
|
||||
Dictionary ret;
|
||||
#ifdef __EMSCRIPTEN__
|
||||
// Don't compile this code at all to avoid undefined references.
|
||||
// Actual virtual call goes to OS_Web.
|
||||
ERR_FAIL_V(ret);
|
||||
#else
|
||||
// Create pipes.
|
||||
int pipe_in[2] = { -1, -1 };
|
||||
int pipe_out[2] = { -1, -1 };
|
||||
int pipe_err[2] = { -1, -1 };
|
||||
|
||||
ERR_FAIL_COND_V(pipe(pipe_in) != 0, ret);
|
||||
if (pipe(pipe_out) != 0) {
|
||||
CLEAN_PIPES
|
||||
ERR_FAIL_V(ret);
|
||||
}
|
||||
if (pipe(pipe_err) != 0) {
|
||||
CLEAN_PIPES
|
||||
ERR_FAIL_V(ret);
|
||||
}
|
||||
|
||||
// Create process.
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) {
|
||||
CLEAN_PIPES
|
||||
ERR_FAIL_V(ret);
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
// The child process.
|
||||
Vector<CharString> cs;
|
||||
cs.push_back(p_path.utf8());
|
||||
for (int i = 0; i < p_arguments.size(); i++) {
|
||||
cs.push_back(p_arguments[i].utf8());
|
||||
}
|
||||
|
||||
Vector<char *> args;
|
||||
for (int i = 0; i < cs.size(); i++) {
|
||||
args.push_back((char *)cs[i].get_data());
|
||||
}
|
||||
args.push_back(0);
|
||||
|
||||
::close(STDIN_FILENO);
|
||||
::dup2(pipe_in[0], STDIN_FILENO);
|
||||
|
||||
::close(STDOUT_FILENO);
|
||||
::dup2(pipe_out[1], STDOUT_FILENO);
|
||||
|
||||
::close(STDERR_FILENO);
|
||||
::dup2(pipe_err[1], STDERR_FILENO);
|
||||
|
||||
CLEAN_PIPES
|
||||
|
||||
execvp(p_path.utf8().get_data(), &args[0]);
|
||||
// The execvp() function only returns if an error occurs.
|
||||
ERR_PRINT("Could not create child process: " + p_path);
|
||||
raise(SIGKILL);
|
||||
}
|
||||
::close(pipe_in[0]);
|
||||
::close(pipe_out[1]);
|
||||
::close(pipe_err[1]);
|
||||
|
||||
Ref<FileAccessUnixPipe> main_pipe;
|
||||
main_pipe.instantiate();
|
||||
main_pipe->open_existing(pipe_out[0], pipe_in[1]);
|
||||
|
||||
Ref<FileAccessUnixPipe> err_pipe;
|
||||
err_pipe.instantiate();
|
||||
err_pipe->open_existing(pipe_err[0], 0);
|
||||
|
||||
ret["stdio"] = main_pipe;
|
||||
ret["stderr"] = err_pipe;
|
||||
ret["pid"] = pid;
|
||||
|
||||
#undef CLEAN_PIPES
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex, bool p_open_console) {
|
||||
#ifdef __EMSCRIPTEN__
|
||||
// Don't compile this code at all to avoid undefined references.
|
||||
|
||||
Reference in New Issue
Block a user