Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix idle inhibitor closing bus connection too early #466

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ AlwaysBreakTemplateDeclarations: false
BinPackArguments: false
BinPackParameters: true
BreakBeforeBinaryOperators: None
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Linux
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
Expand Down
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);
Loading