feat: modules moved and engine moved to submodule
This commit is contained in:
parent
dfb5e645cd
commit
c33d2130cc
5136 changed files with 225275 additions and 64485 deletions
|
|
@ -580,6 +580,126 @@ Dictionary OS_Unix::get_memory_info() const {
|
|||
return meminfo;
|
||||
}
|
||||
|
||||
#ifndef __GLIBC__
|
||||
void OS_Unix::_load_iconv() {
|
||||
#if defined(MACOS_ENABLED) || defined(IOS_ENABLED)
|
||||
String iconv_lib_aliases[] = { "/usr/lib/libiconv.2.dylib" };
|
||||
String iconv_func_aliases[] = { "iconv" };
|
||||
String charset_lib_aliases[] = { "/usr/lib/libcharset.1.dylib" };
|
||||
#else
|
||||
String iconv_lib_aliases[] = { "", "libiconv.2.so", "libiconv.so" };
|
||||
String iconv_func_aliases[] = { "libiconv", "iconv", "bsd_iconv", "rpl_iconv" };
|
||||
String charset_lib_aliases[] = { "", "libcharset.1.so", "libcharset.so" };
|
||||
#endif
|
||||
|
||||
for (size_t i = 0; i < sizeof(iconv_lib_aliases) / sizeof(iconv_lib_aliases[0]); i++) {
|
||||
void *iconv_lib = iconv_lib_aliases[i].is_empty() ? RTLD_NEXT : dlopen(iconv_lib_aliases[i].utf8().get_data(), RTLD_NOW);
|
||||
if (iconv_lib) {
|
||||
for (size_t j = 0; j < sizeof(iconv_func_aliases) / sizeof(iconv_func_aliases[0]); j++) {
|
||||
gd_iconv_open = (PIConvOpen)dlsym(iconv_lib, (iconv_func_aliases[j] + "_open").utf8().get_data());
|
||||
gd_iconv = (PIConv)dlsym(iconv_lib, (iconv_func_aliases[j]).utf8().get_data());
|
||||
gd_iconv_close = (PIConvClose)dlsym(iconv_lib, (iconv_func_aliases[j] + "_close").utf8().get_data());
|
||||
if (gd_iconv_open && gd_iconv && gd_iconv_close) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (gd_iconv_open && gd_iconv && gd_iconv_close) {
|
||||
break;
|
||||
}
|
||||
if (!iconv_lib_aliases[i].is_empty()) {
|
||||
dlclose(iconv_lib);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < sizeof(charset_lib_aliases) / sizeof(charset_lib_aliases[0]); i++) {
|
||||
void *cs_lib = charset_lib_aliases[i].is_empty() ? RTLD_NEXT : dlopen(charset_lib_aliases[i].utf8().get_data(), RTLD_NOW);
|
||||
if (cs_lib) {
|
||||
gd_locale_charset = (PIConvLocaleCharset)dlsym(cs_lib, "locale_charset");
|
||||
if (gd_locale_charset) {
|
||||
break;
|
||||
}
|
||||
if (!charset_lib_aliases[i].is_empty()) {
|
||||
dlclose(cs_lib);
|
||||
}
|
||||
}
|
||||
}
|
||||
_iconv_ok = gd_iconv_open && gd_iconv && gd_iconv_close && gd_locale_charset;
|
||||
}
|
||||
#endif
|
||||
|
||||
String OS_Unix::multibyte_to_string(const String &p_encoding, const PackedByteArray &p_array) const {
|
||||
ERR_FAIL_COND_V_MSG(!_iconv_ok, String(), "Conversion failed: Unable to load libiconv");
|
||||
|
||||
LocalVector<char> chars;
|
||||
#ifdef __GLIBC__
|
||||
gd_iconv_t ctx = gd_iconv_open("UTF-8", p_encoding.is_empty() ? nl_langinfo(CODESET) : p_encoding.utf8().get_data());
|
||||
#else
|
||||
gd_iconv_t ctx = gd_iconv_open("UTF-8", p_encoding.is_empty() ? gd_locale_charset() : p_encoding.utf8().get_data());
|
||||
#endif
|
||||
ERR_FAIL_COND_V_MSG(ctx == (gd_iconv_t)(-1), String(), "Conversion failed: Unknown encoding");
|
||||
|
||||
char *in_ptr = (char *)p_array.ptr();
|
||||
size_t in_size = p_array.size();
|
||||
|
||||
chars.resize(in_size);
|
||||
char *out_ptr = (char *)chars.ptr();
|
||||
size_t out_size = chars.size();
|
||||
|
||||
while (gd_iconv(ctx, &in_ptr, &in_size, &out_ptr, &out_size) == (size_t)-1) {
|
||||
if (errno != E2BIG) {
|
||||
gd_iconv_close(ctx);
|
||||
ERR_FAIL_V_MSG(String(), vformat("Conversion failed: %d - %s", errno, strerror(errno)));
|
||||
}
|
||||
int64_t rate = (chars.size()) / (p_array.size() - in_size);
|
||||
size_t oldpos = chars.size() - out_size;
|
||||
chars.resize(chars.size() + in_size * rate);
|
||||
out_ptr = (char *)chars.ptr() + oldpos;
|
||||
out_size = chars.size() - oldpos;
|
||||
}
|
||||
chars.resize(chars.size() - out_size);
|
||||
gd_iconv_close(ctx);
|
||||
|
||||
return String::utf8((const char *)chars.ptr(), chars.size());
|
||||
}
|
||||
|
||||
PackedByteArray OS_Unix::string_to_multibyte(const String &p_encoding, const String &p_string) const {
|
||||
ERR_FAIL_COND_V_MSG(!_iconv_ok, PackedByteArray(), "Conversion failed: Unable to load libiconv");
|
||||
|
||||
CharString charstr = p_string.utf8();
|
||||
|
||||
PackedByteArray ret;
|
||||
#ifdef __GLIBC__
|
||||
gd_iconv_t ctx = gd_iconv_open(p_encoding.is_empty() ? nl_langinfo(CODESET) : p_encoding.utf8().get_data(), "UTF-8");
|
||||
#else
|
||||
gd_iconv_t ctx = gd_iconv_open(p_encoding.is_empty() ? gd_locale_charset() : p_encoding.utf8().get_data(), "UTF-8");
|
||||
#endif
|
||||
ERR_FAIL_COND_V_MSG(ctx == (gd_iconv_t)(-1), PackedByteArray(), "Conversion failed: Unknown encoding");
|
||||
|
||||
char *in_ptr = (char *)charstr.ptr();
|
||||
size_t in_size = charstr.size();
|
||||
|
||||
ret.resize(in_size);
|
||||
char *out_ptr = (char *)ret.ptrw();
|
||||
size_t out_size = ret.size();
|
||||
|
||||
while (gd_iconv(ctx, &in_ptr, &in_size, &out_ptr, &out_size) == (size_t)-1) {
|
||||
if (errno != E2BIG) {
|
||||
gd_iconv_close(ctx);
|
||||
ERR_FAIL_V_MSG(PackedByteArray(), vformat("Conversion failed: %d - %s", errno, strerror(errno)));
|
||||
}
|
||||
int64_t rate = (ret.size()) / (charstr.size() - in_size);
|
||||
size_t oldpos = ret.size() - out_size;
|
||||
ret.resize(ret.size() + in_size * rate);
|
||||
out_ptr = (char *)ret.ptrw() + oldpos;
|
||||
out_size = ret.size() - oldpos;
|
||||
}
|
||||
ret.resize(ret.size() - out_size);
|
||||
gd_iconv_close(ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Dictionary OS_Unix::execute_with_pipe(const String &p_path, const List<String> &p_arguments, bool p_blocking) {
|
||||
#define CLEAN_PIPES \
|
||||
if (pipe_in[0] >= 0) { \
|
||||
|
|
@ -685,6 +805,57 @@ Dictionary OS_Unix::execute_with_pipe(const String &p_path, const List<String> &
|
|||
#endif
|
||||
}
|
||||
|
||||
int OS_Unix::_wait_for_pid_completion(const pid_t p_pid, int *r_status, int p_options) {
|
||||
while (true) {
|
||||
if (waitpid(p_pid, r_status, p_options) != -1) {
|
||||
// Thread exited normally.
|
||||
return 0;
|
||||
}
|
||||
const int error = errno;
|
||||
if (error == EINTR) {
|
||||
// We're in a debugger, should call waitpid again.
|
||||
// See https://stackoverflow.com/a/45472920/730797.
|
||||
continue;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
bool OS_Unix::_check_pid_is_running(const pid_t p_pid, int *r_status) const {
|
||||
const ProcessInfo *pi = process_map->getptr(p_pid);
|
||||
|
||||
if (pi && !pi->is_running) {
|
||||
// Can return cached value.
|
||||
if (r_status) {
|
||||
*r_status = pi->exit_code;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int status = 0;
|
||||
const int result = _wait_for_pid_completion(p_pid, &status, WNOHANG);
|
||||
if (result == 0) {
|
||||
// Thread is still running.
|
||||
return true;
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_V_MSG(result == -1, false, vformat("Thread %d exited with errno: %d", (int)p_pid, errno));
|
||||
// Thread exited normally.
|
||||
|
||||
status = WIFEXITED(status) ? WEXITSTATUS(status) : status;
|
||||
|
||||
if (pi) {
|
||||
pi->is_running = false;
|
||||
pi->exit_code = status;
|
||||
}
|
||||
|
||||
if (r_status) {
|
||||
*r_status = status;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
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.
|
||||
|
|
@ -710,7 +881,7 @@ Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, St
|
|||
p_pipe_mutex->lock();
|
||||
}
|
||||
String pipe_out;
|
||||
if (pipe_out.parse_utf8(buf) == OK) {
|
||||
if (pipe_out.append_utf8(buf) == OK) {
|
||||
(*r_pipe) += pipe_out;
|
||||
} else {
|
||||
(*r_pipe) += String(buf); // If not valid UTF-8 try decode as Latin-1
|
||||
|
|
@ -750,12 +921,12 @@ Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, St
|
|||
raise(SIGKILL);
|
||||
}
|
||||
|
||||
int status;
|
||||
waitpid(pid, &status, 0);
|
||||
int status = 0;
|
||||
const int result = _wait_for_pid_completion(pid, &status, 0);
|
||||
if (r_exitcode) {
|
||||
*r_exitcode = WIFEXITED(status) ? WEXITSTATUS(status) : status;
|
||||
}
|
||||
return OK;
|
||||
return result ? FAILED : OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -809,7 +980,7 @@ Error OS_Unix::kill(const ProcessID &p_pid) {
|
|||
if (!ret) {
|
||||
//avoid zombie process
|
||||
int st;
|
||||
::waitpid(p_pid, &st, 0);
|
||||
_wait_for_pid_completion(p_pid, &st, 0);
|
||||
}
|
||||
return ret ? ERR_INVALID_PARAMETER : OK;
|
||||
}
|
||||
|
|
@ -820,42 +991,19 @@ int OS_Unix::get_process_id() const {
|
|||
|
||||
bool OS_Unix::is_process_running(const ProcessID &p_pid) const {
|
||||
MutexLock lock(process_map_mutex);
|
||||
const ProcessInfo *pi = process_map->getptr(p_pid);
|
||||
|
||||
if (pi && !pi->is_running) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int status = 0;
|
||||
if (waitpid(p_pid, &status, WNOHANG) != 0) {
|
||||
if (pi) {
|
||||
pi->is_running = false;
|
||||
pi->exit_code = status;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return _check_pid_is_running(p_pid, nullptr);
|
||||
}
|
||||
|
||||
int OS_Unix::get_process_exit_code(const ProcessID &p_pid) const {
|
||||
MutexLock lock(process_map_mutex);
|
||||
const ProcessInfo *pi = process_map->getptr(p_pid);
|
||||
|
||||
if (pi && !pi->is_running) {
|
||||
return pi->exit_code;
|
||||
int exit_code = 0;
|
||||
if (_check_pid_is_running(p_pid, &exit_code)) {
|
||||
// Thread is still running
|
||||
return -1;
|
||||
}
|
||||
|
||||
int status = 0;
|
||||
if (waitpid(p_pid, &status, WNOHANG) != 0) {
|
||||
status = WIFEXITED(status) ? WEXITSTATUS(status) : status;
|
||||
if (pi) {
|
||||
pi->is_running = false;
|
||||
pi->exit_code = status;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
return -1;
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
String OS_Unix::get_locale() const {
|
||||
|
|
@ -942,7 +1090,7 @@ String OS_Unix::get_environment(const String &p_var) const {
|
|||
return "";
|
||||
}
|
||||
String s;
|
||||
if (s.parse_utf8(val) == OK) {
|
||||
if (s.append_utf8(val) == OK) {
|
||||
return s;
|
||||
}
|
||||
return String(val); // Not valid UTF-8, so return as-is
|
||||
|
|
@ -971,7 +1119,7 @@ String OS_Unix::get_executable_path() const {
|
|||
ssize_t len = readlink("/proc/self/exe", buf, sizeof(buf));
|
||||
String b;
|
||||
if (len > 0) {
|
||||
b.parse_utf8(buf, len);
|
||||
b.append_utf8(buf, len);
|
||||
}
|
||||
if (b.is_empty()) {
|
||||
WARN_PRINT("Couldn't get executable path from /proc/self/exe, using argv[0]");
|
||||
|
|
@ -1007,9 +1155,8 @@ String OS_Unix::get_executable_path() const {
|
|||
WARN_PRINT("Couldn't get executable path from sysctl");
|
||||
return OS::get_executable_path();
|
||||
}
|
||||
String b;
|
||||
b.parse_utf8(buf);
|
||||
return b;
|
||||
|
||||
return String::utf8(buf);
|
||||
#elif defined(__APPLE__)
|
||||
char temp_path[1];
|
||||
uint32_t buff_size = 1;
|
||||
|
|
@ -1082,6 +1229,10 @@ void UnixTerminalLogger::log_error(const char *p_function, const char *p_file, i
|
|||
UnixTerminalLogger::~UnixTerminalLogger() {}
|
||||
|
||||
OS_Unix::OS_Unix() {
|
||||
#ifndef __GLIBC__
|
||||
_load_iconv();
|
||||
#endif
|
||||
|
||||
Vector<Logger *> loggers;
|
||||
loggers.push_back(memnew(UnixTerminalLogger));
|
||||
_set_logger(memnew(CompositeLogger(loggers)));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue