Skip to content

Commit

Permalink
Fix idle inhibitor closing bus connection too early
Browse files Browse the repository at this point in the history
  • Loading branch information
notpeelz authored and afayaz-feral committed Mar 27, 2024
1 parent 7d55ef8 commit c854772
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 57 deletions.
14 changes: 10 additions & 4 deletions daemon/gamemode-context.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ struct GameModeContext {

struct GameModeCPUInfo *cpu; /**<Stored CPU info for the current CPU */

GameModeIdleInhibitor *idle_inhibitor;

bool igpu_optimization_enabled;
uint32_t last_cpu_energy_uj;
uint32_t last_igpu_energy_uj;
Expand Down Expand Up @@ -423,8 +425,10 @@ static void game_mode_context_enter(GameModeContext *self)
}

/* Inhibit the screensaver */
if (config_get_inhibit_screensaver(self->config))
game_mode_inhibit_screensaver(true);
if (config_get_inhibit_screensaver(self->config)) {
game_mode_destroy_idle_inhibitor(self->idle_inhibitor);
self->idle_inhibitor = game_mode_create_idle_inhibitor();
}

game_mode_disable_splitlock(self, true);

Expand Down Expand Up @@ -460,8 +464,10 @@ static void game_mode_context_leave(GameModeContext *self)
game_mode_unpark_cpu(self->cpu);

/* UnInhibit the screensaver */
if (config_get_inhibit_screensaver(self->config))
game_mode_inhibit_screensaver(false);
if (config_get_inhibit_screensaver(self->config)) {
game_mode_destroy_idle_inhibitor(self->idle_inhibitor);
self->idle_inhibitor = NULL;
}

game_mode_disable_splitlock(self, false);

Expand Down
129 changes: 77 additions & 52 deletions daemon/gamemode-dbus.c
Original file line number Diff line number Diff line change
Expand Up @@ -708,81 +708,106 @@ void game_mode_context_loop(GameModeContext *context)
}
}

struct GameModeIdleInhibitor {
sd_bus *bus;
unsigned int cookie;
};

/**
* Attempts to inhibit the screensaver
* Uses the "org.freedesktop.ScreenSaver" interface
*/
static unsigned int screensaver_inhibit_cookie = 0;
int game_mode_inhibit_screensaver(bool inhibit)
GameModeIdleInhibitor *game_mode_create_idle_inhibitor(void)
{
const char *service = "org.freedesktop.ScreenSaver";
const char *object_path = "/org/freedesktop/ScreenSaver";
const char *interface = "org.freedesktop.ScreenSaver";
const char *function = inhibit ? "Inhibit" : "UnInhibit";

sd_bus_message *msg = NULL;
sd_bus *bus_local = NULL;
sd_bus_error err;
memset(&err, 0, sizeof(sd_bus_error));

int result = -1;
sd_bus_error err = SD_BUS_ERROR_NULL;

// Open the user bus
int ret = sd_bus_open_user(&bus_local);
if (ret < 0) {
LOG_ERROR("Could not connect to user bus: %s\n", strerror(-ret));
return -1;
return NULL;
}

if (inhibit) {
ret = sd_bus_call_method(bus_local,
service,
object_path,
interface,
function,
&err,
&msg,
"ss",
"com.feralinteractive.GameMode",
"GameMode Activated");
} else {
ret = sd_bus_call_method(bus_local,
service,
object_path,
interface,
function,
&err,
&msg,
"u",
screensaver_inhibit_cookie);
}
ret = sd_bus_call_method(bus_local,
"org.freedesktop.ScreenSaver",
"/org/freedesktop/ScreenSaver",
"org.freedesktop.ScreenSaver",
"Inhibit",
&err,
&msg,
"ss",
"com.feralinteractive.GameMode",
"GameMode Activated");

if (ret < 0) {
LOG_ERROR(
"Could not call %s on %s: %s\n"
"Failed to call Inhibit on org.freedesktop.ScreenSaver: %s\n"
"\t%s\n"
"\t%s\n",
function,
service,
strerror(-ret),
err.name,
err.message);
} else if (inhibit) {
// Read the reply
ret = sd_bus_message_read(msg, "u", &screensaver_inhibit_cookie);
if (ret < 0) {
LOG_ERROR("Failure to parse response from %s on %s: %s\n",
function,
service,
strerror(-ret));
} else {
result = 0;
}
} else {
result = 0;
sd_bus_close(bus_local);
sd_bus_unrefp(&bus_local);
return NULL;
}

// Read the reply
unsigned int cookie = 0;
ret = sd_bus_message_read(msg, "u", &cookie);
if (ret < 0) {
LOG_ERROR("Invalid response from Inhibit on org.freedesktop.ScreenSaver: %s\n",
strerror(-ret));
sd_bus_close(bus_local);
sd_bus_unrefp(&bus_local);
return NULL;
}

GameModeIdleInhibitor *inhibitor = malloc(sizeof(GameModeIdleInhibitor));
if (inhibitor == NULL) {
sd_bus_close(bus_local);
sd_bus_unrefp(&bus_local);
return NULL;
}

inhibitor->bus = bus_local;
inhibitor->cookie = cookie;

return inhibitor;
}

void game_mode_destroy_idle_inhibitor(GameModeIdleInhibitor *inhibitor)
{
sd_bus_message *msg = NULL;
sd_bus_error err = SD_BUS_ERROR_NULL;

if (inhibitor == NULL) {
return;
}

sd_bus_unref(bus_local);
int ret = sd_bus_call_method(inhibitor->bus,
"org.freedesktop.ScreenSaver",
"/org/freedesktop/ScreenSaver",
"org.freedesktop.ScreenSaver",
"UnInhibit",
&err,
&msg,
"u",
inhibitor->cookie);

if (ret < 0) {
LOG_ERROR(
"Failed to call UnInhibit on org.freedesktop.ScreenSaver: %s\n"
"\t%s\n"
"\t%s\n",
strerror(-ret),
err.name,
err.message);
}

return result;
sd_bus_close(inhibitor->bus);
sd_bus_unrefp(&inhibitor->bus);
free(inhibitor);
}
4 changes: 3 additions & 1 deletion daemon/gamemode.h
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,9 @@ void game_mode_undo_core_pinning(const GameModeCPUInfo *info, const pid_t client
/** gamemode-dbus.c
* Provides an API interface for using dbus
*/
typedef struct GameModeIdleInhibitor GameModeIdleInhibitor;
void game_mode_context_loop(GameModeContext *context) __attribute__((noreturn));
int game_mode_inhibit_screensaver(bool inhibit);
GameModeIdleInhibitor *game_mode_create_idle_inhibitor(void);
void game_mode_destroy_idle_inhibitor(GameModeIdleInhibitor *inhibitor);
void game_mode_client_registered(pid_t);
void game_mode_client_unregistered(pid_t);

0 comments on commit c854772

Please sign in to comment.