core: fix sleep delay and simplify process spawning (#127)

* core: fix sleep delay and simplify process spawning

* core: duplicate the inhibit fd with F_DUPFD_CLOEXEC

* nullptr and static

* core: use hyprutils CProcess
This commit is contained in:
Maximilian Seidler 2025-02-27 23:16:45 +00:00 committed by GitHub
parent 3e30a63b5d
commit 9d97c22883
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 26 additions and 52 deletions

View file

@ -10,6 +10,7 @@
#include <algorithm> #include <algorithm>
#include <thread> #include <thread>
#include <mutex> #include <mutex>
#include <hyprutils/os/Process.hpp>
CHypridle::CHypridle() { CHypridle::CHypridle() {
m_sWaylandState.display = wl_display_connect(nullptr); m_sWaylandState.display = wl_display_connect(nullptr);
@ -235,53 +236,13 @@ void CHypridle::enterEventLoop() {
static void spawn(const std::string& args) { static void spawn(const std::string& args) {
Debug::log(LOG, "Executing {}", args); Debug::log(LOG, "Executing {}", args);
int socket[2]; Hyprutils::OS::CProcess proc("/bin/sh", {"-c", args});
if (pipe(socket) != 0) { if (!proc.runAsync()) {
Debug::log(LOG, "Unable to create pipe for fork"); Debug::log(ERR, "Failed run \"{}\"", args);
}
pid_t child, grandchild;
child = fork();
if (child < 0) {
close(socket[0]);
close(socket[1]);
Debug::log(LOG, "Fail to create the first fork");
return;
}
if (child == 0) {
// run in child
sigset_t set;
sigemptyset(&set);
sigprocmask(SIG_SETMASK, &set, nullptr);
grandchild = fork();
if (grandchild == 0) {
// run in grandchild
close(socket[0]);
close(socket[1]);
execl("/bin/sh", "/bin/sh", "-c", args.c_str(), nullptr);
// exit grandchild
_exit(0);
}
close(socket[0]);
write(socket[1], &grandchild, sizeof(grandchild));
close(socket[1]);
// exit child
_exit(0);
}
// run in parent
close(socket[1]);
read(socket[0], &grandchild, sizeof(grandchild));
close(socket[0]);
// clear child and leave grandchild to init
waitpid(child, nullptr, 0);
if (grandchild < 0) {
Debug::log(LOG, "Failed to create the second fork");
return; return;
} }
Debug::log(LOG, "Process Created with pid {}", grandchild); Debug::log(LOG, "Process Created with pid {}", proc.pid());
} }
void CHypridle::onIdled(SIdleListener* pListener) { void CHypridle::onIdled(SIdleListener* pListener) {
@ -424,7 +385,7 @@ static void handleDbusLogin(sdbus::Message msg) {
Debug::log(LOG, "Got Unlock from dbus"); Debug::log(LOG, "Got Unlock from dbus");
if (!std::string{*UNLOCKCMD}.empty()) { if (!std::string{*UNLOCKCMD}.empty()) {
Debug::log(LOG, "Locking with {}", *UNLOCKCMD); Debug::log(LOG, "Unlocking with {}", *UNLOCKCMD);
spawn(*UNLOCKCMD); spawn(*UNLOCKCMD);
} }
} }
@ -456,7 +417,7 @@ static void handleDbusSleep(sdbus::Message msg) {
g_pHypridle->handleInhibitOnDbusSleep(toSleep); g_pHypridle->handleInhibitOnDbusSleep(toSleep);
} }
void handleDbusBlockInhibits(const std::string& inhibits) { static void handleDbusBlockInhibits(const std::string& inhibits) {
static auto inhibited = false; static auto inhibited = false;
// BlockInhibited is a colon separated list of inhibit types. Wrapping in additional colons allows for easier checking if there are active inhibits we are interested in // BlockInhibited is a colon separated list of inhibit types. Wrapping in additional colons allows for easier checking if there are active inhibits we are interested in
auto inhibits_ = ":" + inhibits + ":"; auto inhibits_ = ":" + inhibits + ":";
@ -609,6 +570,11 @@ void CHypridle::handleInhibitOnDbusSleep(bool toSleep) {
} }
void CHypridle::inhibitSleep() { void CHypridle::inhibitSleep() {
if (m_sDBUSState.sleepInhibitFd.isValid()) {
Debug::log(WARN, "Called inhibitSleep, but previous sleep inhibitor is still active!");
m_sDBUSState.sleepInhibitFd.reset();
}
auto method = m_sDBUSState.login->createMethodCall(sdbus::InterfaceName{"org.freedesktop.login1.Manager"}, sdbus::MethodName{"Inhibit"}); auto method = m_sDBUSState.login->createMethodCall(sdbus::InterfaceName{"org.freedesktop.login1.Manager"}, sdbus::MethodName{"Inhibit"});
method << "sleep"; method << "sleep";
method << "hypridle"; method << "hypridle";
@ -628,11 +594,18 @@ void CHypridle::inhibitSleep() {
return; return;
} }
reply >> m_sDBUSState.sleepInhibitFd; sdbus::UnixFd fd;
Debug::log(TRACE, "Inhibited sleep with fd {}", m_sDBUSState.sleepInhibitFd.get()); // This calls dup on the fd, no F_DUPFD_CLOEXEC :(
} catch (const std::exception& e) { Debug::log(ERR, "Failed to inhibit sleep ({})", e.what()); } // There seems to be no way to get the file descriptor out of the reply other than that.
reply >> fd;
Debug::log(LOG, "Inhibited sleep!"); // Setting the O_CLOEXEC flag does not work for some reason. Instead we make our own dupe and close the one from UnixFd.
auto immidiateFD = Hyprutils::OS::CFileDescriptor(fd.release());
m_sDBUSState.sleepInhibitFd = immidiateFD.duplicate(F_DUPFD_CLOEXEC);
immidiateFD.reset(); // close the fd that was opened with dup
Debug::log(LOG, "Inhibited sleep with fd {}", m_sDBUSState.sleepInhibitFd.get());
} catch (const std::exception& e) { Debug::log(ERR, "Failed to inhibit sleep ({})", e.what()); }
} }
void CHypridle::uninhibitSleep() { void CHypridle::uninhibitSleep() {
@ -642,5 +615,5 @@ void CHypridle::uninhibitSleep() {
} }
Debug::log(LOG, "Releasing the sleep inhibitor!"); Debug::log(LOG, "Releasing the sleep inhibitor!");
close(m_sDBUSState.sleepInhibitFd.release()); m_sDBUSState.sleepInhibitFd.reset();
} }

View file

@ -3,6 +3,7 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <sdbus-c++/sdbus-c++.h> #include <sdbus-c++/sdbus-c++.h>
#include <hyprutils/os/FileDescriptor.hpp>
#include <condition_variable> #include <condition_variable>
#include "wayland.hpp" #include "wayland.hpp"
@ -83,7 +84,7 @@ class CHypridle {
std::unique_ptr<sdbus::IProxy> login; std::unique_ptr<sdbus::IProxy> login;
std::vector<std::unique_ptr<sdbus::IObject>> screenSaverObjects; std::vector<std::unique_ptr<sdbus::IObject>> screenSaverObjects;
std::vector<SDbusInhibitCookie> inhibitCookies; std::vector<SDbusInhibitCookie> inhibitCookies;
sdbus::UnixFd sleepInhibitFd; Hyprutils::OS::CFileDescriptor sleepInhibitFd;
} m_sDBUSState; } m_sDBUSState;
struct { struct {