From 21b533ae4764590934a53d5bd1f480eff7272161 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20B=C3=A1lint=20Misius?= Date: Sat, 16 Aug 2025 14:33:24 +0200 Subject: [PATCH] Fix opening URIs hanging the game on freedesktop systems Apparently xdg-open was meant to hang all this time and we're supposed to not wait for it, ok then: https://github.com/xgqt-org/xdg-utils/blob/5f7169ec0ff1b15e645c10566678b6cc062795dc/scripts/desc/xdg-open.xml#L148 Also stop using system(3). --- src/common/platform/Linux.cpp | 64 +++++++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 11 deletions(-) diff --git a/src/common/platform/Linux.cpp b/src/common/platform/Linux.cpp index 6dde305bb..1f8c634e8 100644 --- a/src/common/platform/Linux.cpp +++ b/src/common/platform/Linux.cpp @@ -6,18 +6,59 @@ #include "Config.h" #include #include +#include +#include +#include #ifdef __FreeBSD__ # include #endif +static bool Run(const char *what, std::vector cmd, bool check) +{ + auto pid = fork(); + if (pid == -1) + { + std::cerr << what << ": fork failed: errno " << errno << ": " << strerror(errno) << std::endl; + return false; + } + if (pid == 0) + { + std::vector argv; + for (auto &p : cmd) + { + argv.push_back(const_cast(p.c_str())); // not really a problem hopefully + } + argv.push_back(nullptr); + execvp(argv[0], argv.data()); + exit(1); // exec failed >_> + } + if (check) + { + int status; + if (waitpid(pid, &status, 0) != pid) + { + std::cerr << what << ": child possibly failed: errno " << errno << ": " << strerror(errno) << std::endl; + return false; + } + if (!WIFEXITED(status)) + { + std::cerr << what << ": child possibly failed: waitpid status " << status << std::endl; + return false; + } + if (WEXITSTATUS(status)) + { + std::cerr << what << ": child failed: exit status " << WEXITSTATUS(status) << std::endl; + return false; + } + } + return true; +} + namespace Platform { void OpenURI(ByteString uri) { - if (system(("xdg-open \"" + uri + "\"").c_str())) - { - fprintf(stderr, "cannot open URI: system(...) failed\n"); - } + Run("opening URI", { "xdg-open", uri }, false); } long unsigned int GetTime() @@ -100,35 +141,36 @@ bool Install() desktopData += ByteString::Build("Path=", desktopEscapeString(path), "\n"); ByteString file = ByteString::Build(APPVENDOR, "-", APPID, ".desktop"); ok = ok && Platform::WriteFile(desktopData, file); - ok = ok && !system(ByteString::Build("xdg-desktop-menu install ", file).c_str()); - ok = ok && !system(ByteString::Build("xdg-mime default ", file, " application/vnd.powdertoy.save").c_str()); - ok = ok && !system(ByteString::Build("xdg-mime default ", file, " x-scheme-handler/ptsave").c_str()); + ok = ok && Run("installing desktop file", { "xdg-desktop-menu", "install", file }, true); + ok = ok && Run("associating save MIME type with desktop file", { "xdg-mime", "default", file, "application/vnd.powdertoy.save" }, true); + ok = ok && Run("associating ptsave URL scheme with desktop file", { "xdg-mime", "default", file, "x-scheme-handler/ptsave" }, true); Platform::RemoveFile(file); } if (ok) { ByteString file = ByteString(APPVENDOR) + "-save.xml"; ok = ok && Platform::WriteFile(save_xml.AsCharSpan(), file); - ok = ok && !system(ByteString::Build("xdg-mime install ", file).c_str()); + ok = ok && Run("associating saves and stamps with save MIME type with desktop file", { "xdg-mime", "install", file }, true); Platform::RemoveFile(file); } if (ok) { ByteString file = ByteString(APPVENDOR) + "-cps.png"; ok = ok && Platform::WriteFile(icon_cps_png.AsCharSpan(), file); - ok = ok && !system(ByteString::Build("xdg-icon-resource install --noupdate --context mimetypes --size 64 ", file, " application-vnd.powdertoy.save").c_str()); + ok = ok && Run("providing file icons for saves and stamps", { "xdg-icon-resource", "install", "--noupdate", "--context", "mimetypes", "--size", "64", file, "application-vnd.powdertoy.save" }, true); Platform::RemoveFile(file); } if (ok) { ByteString file = ByteString(APPVENDOR) + "-exe.png"; + auto vendoredName = ByteString::Build(APPVENDOR, "-", APPEXE); ok = ok && Platform::WriteFile(icon_exe_png.AsCharSpan(), file); - ok = ok && !system(ByteString::Build("xdg-icon-resource install --noupdate --size 64 ", file, " ", APPVENDOR, "-", APPEXE).c_str()); + ok = ok && Run("providing desktop file icon", { "xdg-icon-resource", "install", "--noupdate", "--size", "64", file, vendoredName }, true); Platform::RemoveFile(file); } if (ok) { - ok = ok && !system("xdg-icon-resource forceupdate"); + ok = ok && Run("updating desktop icons", { "xdg-icon-resource", "forceupdate" }, true); } return ok; }