mirror of
https://github.com/hyprwm/hypridle.git
synced 2025-12-25 03:20:03 +01:00
core: fix sleep delay and simplify process spawning
This commit is contained in:
parent
3e30a63b5d
commit
48fcf3e32e
2 changed files with 56 additions and 48 deletions
|
|
@ -19,7 +19,19 @@ CHypridle::CHypridle() {
|
|||
}
|
||||
}
|
||||
|
||||
void setupSignals(void) {
|
||||
struct sigaction sa;
|
||||
|
||||
// don't transform child processes into zombies and don't handle SIGCHLD.
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = SA_NOCLDSTOP | SA_NOCLDWAIT | SA_RESTART;
|
||||
sa.sa_handler = SIG_DFL;
|
||||
sigaction(SIGCHLD, &sa, NULL);
|
||||
}
|
||||
|
||||
void CHypridle::run() {
|
||||
setupSignals();
|
||||
|
||||
m_sWaylandState.registry = makeShared<CCWlRegistry>((wl_proxy*)wl_display_get_registry(m_sWaylandState.display));
|
||||
m_sWaylandState.registry->setGlobal([this](CCWlRegistry* r, uint32_t name, const char* interface, uint32_t version) {
|
||||
const std::string IFACE = interface;
|
||||
|
|
@ -235,53 +247,30 @@ void CHypridle::enterEventLoop() {
|
|||
static void spawn(const std::string& args) {
|
||||
Debug::log(LOG, "Executing {}", args);
|
||||
|
||||
int socket[2];
|
||||
if (pipe(socket) != 0) {
|
||||
Debug::log(LOG, "Unable to create pipe for fork");
|
||||
}
|
||||
|
||||
pid_t child, grandchild;
|
||||
child = fork();
|
||||
pid_t child = fork();
|
||||
if (child < 0) {
|
||||
close(socket[0]);
|
||||
close(socket[1]);
|
||||
Debug::log(LOG, "Fail to create the first fork");
|
||||
Debug::log(ERR, "Failed to fork");
|
||||
return;
|
||||
}
|
||||
if (child == 0) {
|
||||
// run in child
|
||||
} else if (child == 0) {
|
||||
setsid();
|
||||
|
||||
sigset_t set;
|
||||
sigemptyset(&set);
|
||||
sigprocmask(SIG_SETMASK, &set, nullptr);
|
||||
struct sigaction sa;
|
||||
// reset signals to the default
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = 0;
|
||||
sa.sa_handler = SIG_DFL;
|
||||
sigaction(SIGCHLD, &sa, NULL);
|
||||
|
||||
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;
|
||||
// TODO: ??? Why do we need that ???
|
||||
// We already make sure we have O_CLOEXEC and that should be enough. Still somehow, without this, releasing the inhibitor does not work.
|
||||
// Somehow related to sdbus::UnixFd calling dup on the fd??
|
||||
g_pHypridle->closeInhibitFd();
|
||||
|
||||
execl("/bin/sh", "/bin/sh", "-c", args.c_str(), nullptr);
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
Debug::log(LOG, "Process Created with pid {}", grandchild);
|
||||
Debug::log(LOG, "Process Created with pid {}", child);
|
||||
}
|
||||
|
||||
void CHypridle::onIdled(SIdleListener* pListener) {
|
||||
|
|
@ -424,7 +413,7 @@ static void handleDbusLogin(sdbus::Message msg) {
|
|||
Debug::log(LOG, "Got Unlock from dbus");
|
||||
|
||||
if (!std::string{*UNLOCKCMD}.empty()) {
|
||||
Debug::log(LOG, "Locking with {}", *UNLOCKCMD);
|
||||
Debug::log(LOG, "Unlocking with {}", *UNLOCKCMD);
|
||||
spawn(*UNLOCKCMD);
|
||||
}
|
||||
}
|
||||
|
|
@ -609,6 +598,11 @@ void CHypridle::handleInhibitOnDbusSleep(bool toSleep) {
|
|||
}
|
||||
|
||||
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"});
|
||||
method << "sleep";
|
||||
method << "hypridle";
|
||||
|
|
@ -628,11 +622,18 @@ void CHypridle::inhibitSleep() {
|
|||
return;
|
||||
}
|
||||
|
||||
reply >> m_sDBUSState.sleepInhibitFd;
|
||||
Debug::log(TRACE, "Inhibited sleep with fd {}", m_sDBUSState.sleepInhibitFd.get());
|
||||
} catch (const std::exception& e) { Debug::log(ERR, "Failed to inhibit sleep ({})", e.what()); }
|
||||
sdbus::UnixFd fd;
|
||||
// This calls dup on the fd, no F_DUPFD_CLOEXEC :(
|
||||
// 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!");
|
||||
m_sDBUSState.sleepInhibitFd = Hyprutils::OS::CFileDescriptor(fd.release());
|
||||
auto flags = m_sDBUSState.sleepInhibitFd.getFlags();
|
||||
if (!(flags & O_CLOEXEC) && !m_sDBUSState.sleepInhibitFd.setFlags(flags | O_CLOEXEC))
|
||||
Debug::log(ERR, "Sleep inhibitor has no O_CLOEXEC");
|
||||
|
||||
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() {
|
||||
|
|
@ -642,5 +643,9 @@ void CHypridle::uninhibitSleep() {
|
|||
}
|
||||
|
||||
Debug::log(LOG, "Releasing the sleep inhibitor!");
|
||||
close(m_sDBUSState.sleepInhibitFd.release());
|
||||
m_sDBUSState.sleepInhibitFd.reset();
|
||||
}
|
||||
|
||||
void CHypridle::closeInhibitFd() {
|
||||
m_sDBUSState.sleepInhibitFd.reset();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include <memory>
|
||||
#include <vector>
|
||||
#include <sdbus-c++/sdbus-c++.h>
|
||||
#include <hyprutils/os/FileDescriptor.hpp>
|
||||
#include <condition_variable>
|
||||
|
||||
#include "wayland.hpp"
|
||||
|
|
@ -48,6 +49,8 @@ class CHypridle {
|
|||
void inhibitSleep();
|
||||
void uninhibitSleep();
|
||||
|
||||
void closeInhibitFd();
|
||||
|
||||
private:
|
||||
void setupDBUS();
|
||||
void enterEventLoop();
|
||||
|
|
@ -83,7 +86,7 @@ class CHypridle {
|
|||
std::unique_ptr<sdbus::IProxy> login;
|
||||
std::vector<std::unique_ptr<sdbus::IObject>> screenSaverObjects;
|
||||
std::vector<SDbusInhibitCookie> inhibitCookies;
|
||||
sdbus::UnixFd sleepInhibitFd;
|
||||
Hyprutils::OS::CFileDescriptor sleepInhibitFd;
|
||||
} m_sDBUSState;
|
||||
|
||||
struct {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue