mirror of
https://github.com/Relintai/rcpp_framework.git
synced 2024-11-14 04:57:21 +01:00
Added a new execute method to Platform, and moved the execute method from the crash handler to platform linux.
This commit is contained in:
parent
c94c465d78
commit
8bd6f0aea6
@ -10,6 +10,10 @@ String Platform::get_executable_path() {
|
|||||||
return arg_parser.executable_name;
|
return arg_parser.executable_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Platform::execute(const String &p_path, const Vector<String> &p_arguments, bool p_blocking, int64_t *r_child_id, String *r_pipe, int *r_exitcode, Mutex *p_pipe_mutex, bool read_stderr) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
Platform *Platform::get_singleton() {
|
Platform *Platform::get_singleton() {
|
||||||
return _self;
|
return _self;
|
||||||
}
|
}
|
||||||
|
@ -3,12 +3,16 @@
|
|||||||
|
|
||||||
#include "arg_parser.h"
|
#include "arg_parser.h"
|
||||||
|
|
||||||
|
#include "core/threading/mutex.h"
|
||||||
|
|
||||||
class Platform {
|
class Platform {
|
||||||
public:
|
public:
|
||||||
virtual void arg_setup(int argc, char **argv, char **envp);
|
virtual void arg_setup(int argc, char **argv, char **envp);
|
||||||
|
|
||||||
virtual String get_executable_path();
|
virtual String get_executable_path();
|
||||||
|
|
||||||
|
virtual int execute(const String &p_path, const Vector<String> &p_arguments, bool p_blocking, int64_t *r_child_id = nullptr, String *r_pipe = nullptr, int *r_exitcode = nullptr, Mutex *p_pipe_mutex = nullptr, bool read_stderr = false);
|
||||||
|
|
||||||
static Platform *get_singleton();
|
static Platform *get_singleton();
|
||||||
|
|
||||||
Platform();
|
Platform();
|
||||||
|
@ -48,111 +48,7 @@
|
|||||||
#include "core/containers/vector.h"
|
#include "core/containers/vector.h"
|
||||||
|
|
||||||
#include "core/os/platform.h"
|
#include "core/os/platform.h"
|
||||||
|
#include "core/error_macros.h"
|
||||||
int execute(const String &p_path, const Vector<String> &p_arguments, bool p_blocking, int64_t *r_child_id, String *r_pipe, int *r_exitcode) {
|
|
||||||
#ifdef __EMSCRIPTEN__
|
|
||||||
// Don't compile this code at all to avoid undefined references.
|
|
||||||
// Actual virtual call goes to OS_JavaScript.
|
|
||||||
ERR_FAIL_V(ERR_BUG);
|
|
||||||
#else
|
|
||||||
bool read_stderr = false;
|
|
||||||
//Mutex *p_pipe_mutex;
|
|
||||||
|
|
||||||
if (p_blocking && r_pipe) {
|
|
||||||
String argss;
|
|
||||||
argss = "\"" + p_path + "\"";
|
|
||||||
|
|
||||||
for (int i = 0; i < p_arguments.size(); i++) {
|
|
||||||
argss += String(" \"");
|
|
||||||
argss += p_arguments[i];
|
|
||||||
argss += String("\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (read_stderr) {
|
|
||||||
argss += " 2>&1"; // Read stderr too
|
|
||||||
} else {
|
|
||||||
argss += " 2>/dev/null"; //silence stderr
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE *f = popen(argss.data(), "r");
|
|
||||||
|
|
||||||
if (!f) {
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
//ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, "Cannot pipe stream from process running with following arguments '" + argss + "'.");
|
|
||||||
|
|
||||||
char buf[65535];
|
|
||||||
|
|
||||||
while (fgets(buf, 65535, f)) {
|
|
||||||
//if (p_pipe_mutex) {
|
|
||||||
// p_pipe_mutex->lock();
|
|
||||||
//}
|
|
||||||
|
|
||||||
(*r_pipe) += String::utf8(buf);
|
|
||||||
|
|
||||||
//if (p_pipe_mutex) {
|
|
||||||
// p_pipe_mutex->unlock();
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
|
|
||||||
int rv = pclose(f);
|
|
||||||
|
|
||||||
if (r_exitcode) {
|
|
||||||
*r_exitcode = WEXITSTATUS(rv);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pid_t pid = fork();
|
|
||||||
//ERR_FAIL_COND_V(pid < 0, ERR_CANT_FORK);
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (pid == 0) {
|
|
||||||
// is child
|
|
||||||
|
|
||||||
if (!p_blocking) {
|
|
||||||
// For non blocking calls, create a new session-ID so parent won't wait for it.
|
|
||||||
// This ensures the process won't go zombie at end.
|
|
||||||
setsid();
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector<String> cs;
|
|
||||||
cs.push_back(p_path);
|
|
||||||
for (int i = 0; i < p_arguments.size(); i++) {
|
|
||||||
cs.push_back(p_arguments[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector<char *> args;
|
|
||||||
for (int i = 0; i < cs.size(); i++) {
|
|
||||||
args.push_back((char *)cs[i].c_str());
|
|
||||||
}
|
|
||||||
args.push_back(0);
|
|
||||||
|
|
||||||
execvp(p_path.c_str(), &args[0]);
|
|
||||||
// still alive? something failed..
|
|
||||||
fprintf(stderr, "**ERROR** OS_Unix::execute - Could not create child process while executing: %s\n", p_path.data());
|
|
||||||
|
|
||||||
raise(SIGKILL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p_blocking) {
|
|
||||||
int status;
|
|
||||||
waitpid(pid, &status, 0);
|
|
||||||
if (r_exitcode) {
|
|
||||||
*r_exitcode = WIFEXITED(status) ? WEXITSTATUS(status) : status;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if (r_child_id) {
|
|
||||||
*r_child_id = pid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handle_crash(int sig) {
|
static void handle_crash(int sig) {
|
||||||
void *bt_buffer[256];
|
void *bt_buffer[256];
|
||||||
@ -200,7 +96,7 @@ static void handle_crash(int sig) {
|
|||||||
|
|
||||||
// Try to get the file/line number using addr2line
|
// Try to get the file/line number using addr2line
|
||||||
int ret;
|
int ret;
|
||||||
int err = execute(String("addr2line"), args, true, nullptr, &output, &ret);
|
int err = Platform::get_singleton()->execute(String("addr2line"), args, true, nullptr, &output, &ret);
|
||||||
|
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
output.erase(output.size() - 1, 1);
|
output.erase(output.size() - 1, 1);
|
||||||
|
@ -65,6 +65,111 @@ String PlatformLinux::get_executable_path() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Based on Godot Engine's implementation (MIT license)
|
||||||
|
//Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.
|
||||||
|
//Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).
|
||||||
|
int PlatformLinux::execute(const String &p_path, const Vector<String> &p_arguments, bool p_blocking, int64_t *r_child_id, String *r_pipe, int *r_exitcode, Mutex *p_pipe_mutex, bool read_stderr) {
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
// Don't compile this code at all to avoid undefined references.
|
||||||
|
// Actual virtual call goes to OS_JavaScript.
|
||||||
|
RLOG_ERR("ERROR execute\n");
|
||||||
|
return;
|
||||||
|
#else
|
||||||
|
if (p_blocking && r_pipe) {
|
||||||
|
String argss;
|
||||||
|
argss = "\"" + p_path + "\"";
|
||||||
|
|
||||||
|
for (int i = 0; i < p_arguments.size(); i++) {
|
||||||
|
argss += String(" \"");
|
||||||
|
argss += p_arguments[i];
|
||||||
|
argss += String("\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (read_stderr) {
|
||||||
|
argss += " 2>&1"; // Read stderr too
|
||||||
|
} else {
|
||||||
|
argss += " 2>/dev/null"; //silence stderr
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *f = popen(argss.data(), "r");
|
||||||
|
|
||||||
|
if (!f) {
|
||||||
|
RLOG_ERR("Cannot pipe stream from process running with following arguments '" + argss + "'.\n");
|
||||||
|
ERR_FAIL_COND_V(!f, 2); //ERR_CANT_OPEN
|
||||||
|
}
|
||||||
|
|
||||||
|
char buf[65535];
|
||||||
|
|
||||||
|
while (fgets(buf, 65535, f)) {
|
||||||
|
if (p_pipe_mutex) {
|
||||||
|
p_pipe_mutex->lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
(*r_pipe) += String::utf8(buf);
|
||||||
|
|
||||||
|
if (p_pipe_mutex) {
|
||||||
|
p_pipe_mutex->unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int rv = pclose(f);
|
||||||
|
|
||||||
|
if (r_exitcode) {
|
||||||
|
*r_exitcode = WEXITSTATUS(rv);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pid_t pid = fork();
|
||||||
|
//ERR_FAIL_COND_V(pid < 0, ERR_CANT_FORK);
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (pid == 0) {
|
||||||
|
// is child
|
||||||
|
|
||||||
|
if (!p_blocking) {
|
||||||
|
// For non blocking calls, create a new session-ID so parent won't wait for it.
|
||||||
|
// This ensures the process won't go zombie at end.
|
||||||
|
setsid();
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector<String> cs;
|
||||||
|
cs.push_back(p_path);
|
||||||
|
for (int i = 0; i < p_arguments.size(); i++) {
|
||||||
|
cs.push_back(p_arguments[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector<char *> args;
|
||||||
|
for (int i = 0; i < cs.size(); i++) {
|
||||||
|
args.push_back((char *)cs[i].c_str());
|
||||||
|
}
|
||||||
|
args.push_back(0);
|
||||||
|
|
||||||
|
execvp(p_path.c_str(), &args[0]);
|
||||||
|
// still alive? something failed..
|
||||||
|
fprintf(stderr, "**ERROR** OS_Unix::execute - Could not create child process while executing: %s\n", p_path.data());
|
||||||
|
|
||||||
|
raise(SIGKILL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_blocking) {
|
||||||
|
int status;
|
||||||
|
waitpid(pid, &status, 0);
|
||||||
|
if (r_exitcode) {
|
||||||
|
*r_exitcode = WIFEXITED(status) ? WEXITSTATUS(status) : status;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (r_child_id) {
|
||||||
|
*r_child_id = pid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
PlatformLinux::PlatformLinux() : Platform() {
|
PlatformLinux::PlatformLinux() : Platform() {
|
||||||
}
|
}
|
||||||
PlatformLinux::~PlatformLinux() {
|
PlatformLinux::~PlatformLinux() {
|
||||||
|
@ -7,6 +7,8 @@ class PlatformLinux : public Platform {
|
|||||||
public:
|
public:
|
||||||
virtual String get_executable_path();
|
virtual String get_executable_path();
|
||||||
|
|
||||||
|
virtual int execute(const String &p_path, const Vector<String> &p_arguments, bool p_blocking, int64_t *r_child_id = nullptr, String *r_pipe = nullptr, int *r_exitcode = nullptr, Mutex *p_pipe_mutex = nullptr, bool read_stderr = false);
|
||||||
|
|
||||||
PlatformLinux();
|
PlatformLinux();
|
||||||
virtual ~PlatformLinux();
|
virtual ~PlatformLinux();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user