mirror of
https://github.com/FeralInteractive/gamemode.git
synced 2025-06-06 07:37:21 +02:00
Merge pull request #108 from mdiluz/bug-and-feature-bash
Assorted small bug fixes
This commit is contained in:
commit
cc9f78fe0a
@ -71,6 +71,7 @@ struct GameModeConfig {
|
||||
char whitelist[CONFIG_LIST_MAX][CONFIG_VALUE_MAX];
|
||||
char blacklist[CONFIG_LIST_MAX][CONFIG_VALUE_MAX];
|
||||
|
||||
long script_timeout;
|
||||
char startscripts[CONFIG_LIST_MAX][CONFIG_VALUE_MAX];
|
||||
char endscripts[CONFIG_LIST_MAX][CONFIG_VALUE_MAX];
|
||||
|
||||
@ -278,6 +279,8 @@ static int inih_handler(void *user, const char *section, const char *name, const
|
||||
valid = append_value_to_list(name, value, self->values.startscripts);
|
||||
} else if (strcmp(name, "end") == 0) {
|
||||
valid = append_value_to_list(name, value, self->values.endscripts);
|
||||
} else if (strcmp(name, "script_timeout") == 0) {
|
||||
valid = get_long_value(name, value, &self->values.script_timeout);
|
||||
}
|
||||
}
|
||||
|
||||
@ -330,6 +333,7 @@ static void load_config_files(GameModeConfig *self)
|
||||
self->values.reaper_frequency = DEFAULT_REAPER_FREQ;
|
||||
self->values.gpu_device = -1; /* 0 is a valid device ID so use -1 to indicate no value */
|
||||
self->values.nv_perf_level = -1;
|
||||
self->values.script_timeout = 10; /* Default to 10 seconds for scripts */
|
||||
|
||||
/*
|
||||
* Locations to load, in order
|
||||
@ -506,6 +510,11 @@ void config_get_gamemode_end_scripts(GameModeConfig *self,
|
||||
memcpy_locked_config(self, scripts, self->values.endscripts, sizeof(self->values.startscripts));
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the script timemout value
|
||||
*/
|
||||
DEFINE_CONFIG_GET(script_timeout)
|
||||
|
||||
/*
|
||||
* Get the chosen default governor
|
||||
*/
|
||||
|
@ -105,6 +105,11 @@ void config_get_gamemode_start_scripts(GameModeConfig *self,
|
||||
void config_get_gamemode_end_scripts(GameModeConfig *self,
|
||||
char scripts[CONFIG_LIST_MAX][CONFIG_VALUE_MAX]);
|
||||
|
||||
/*
|
||||
* Get the script timout value
|
||||
*/
|
||||
long config_get_script_timeout(GameModeConfig *self);
|
||||
|
||||
/*
|
||||
* Get the chosen default governor
|
||||
*/
|
||||
|
@ -37,20 +37,49 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <linux/limits.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/wait.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static const int default_timout = 5;
|
||||
|
||||
/**
|
||||
* Call an external process
|
||||
*/
|
||||
int run_external_process(const char *const *exec_args)
|
||||
int run_external_process(const char *const *exec_args, char buffer[EXTERNAL_BUFFER_MAX], int tsec)
|
||||
{
|
||||
pid_t p;
|
||||
int status = 0;
|
||||
int pipes[2];
|
||||
char internal[EXTERNAL_BUFFER_MAX] = { 0 };
|
||||
|
||||
if (pipe(pipes) == -1) {
|
||||
LOG_ERROR("Could not create pipe: %s!\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set the default timeout */
|
||||
if (tsec == -1) {
|
||||
tsec = default_timout;
|
||||
}
|
||||
|
||||
/* set up our signaling for the child and the timout */
|
||||
sigset_t mask;
|
||||
sigset_t omask;
|
||||
sigemptyset(&mask);
|
||||
sigaddset(&mask, SIGCHLD);
|
||||
if (sigprocmask(SIG_BLOCK, &mask, &omask) < 0) {
|
||||
LOG_ERROR("sigprocmask failed: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((p = fork()) < 0) {
|
||||
LOG_ERROR("Failed to fork(): %s\n", strerror(errno));
|
||||
return false;
|
||||
} else if (p == 0) {
|
||||
/* Send STDOUT to the pipe */
|
||||
dup2(pipes[1], STDOUT_FILENO);
|
||||
close(pipes[0]);
|
||||
close(pipes[1]);
|
||||
/* Execute the command */
|
||||
/* Note about cast:
|
||||
* The statement about argv[] and envp[] being constants is
|
||||
@ -65,54 +94,30 @@ int run_external_process(const char *const *exec_args)
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
if (waitpid(p, &status, 0) < 0) {
|
||||
LOG_ERROR("Failed to waitpid(%d): %s\n", (int)p, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
/* Set up the timout */
|
||||
struct timespec timeout;
|
||||
timeout.tv_sec = tsec; /* Magic timeout value of 5s for now - should be sane for most commands
|
||||
*/
|
||||
timeout.tv_nsec = 0;
|
||||
|
||||
/* i.e. sigsev */
|
||||
if (!WIFEXITED(status)) {
|
||||
LOG_ERROR("Child process '%s' exited abnormally\n", exec_args[0]);
|
||||
} else if (WEXITSTATUS(status) != 0) {
|
||||
LOG_ERROR("External process failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call an external process and get output
|
||||
*/
|
||||
int run_external_process_get_output(const char *const *exec_args, char buffer[EXTERNAL_BUFFER_MAX])
|
||||
{
|
||||
pid_t p;
|
||||
int status = 0;
|
||||
int pipes[2];
|
||||
|
||||
if (pipe(pipes) == -1) {
|
||||
LOG_ERROR("Could not create pipe: %s!\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((p = fork()) < 0) {
|
||||
LOG_ERROR("Failed to fork(): %s\n", strerror(errno));
|
||||
return false;
|
||||
} else if (p == 0) {
|
||||
/* Send STDOUT to the pipe */
|
||||
dup2(pipes[1], STDOUT_FILENO);
|
||||
close(pipes[0]);
|
||||
close(pipes[1]);
|
||||
/* Launch the process */
|
||||
if (execv(exec_args[0], (char *const *)exec_args) != 0) {
|
||||
LOG_ERROR("Failed to execute external process %s: %s\n", exec_args[0], strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
/* Wait for the child to finish up with a timout */
|
||||
while (true) {
|
||||
if (sigtimedwait(&mask, NULL, &timeout) < 0) {
|
||||
if (errno == EINTR) {
|
||||
continue;
|
||||
} else if (errno == EAGAIN) {
|
||||
LOG_ERROR("Child process timed out for %s, killing and returning\n", exec_args[0]);
|
||||
kill(p, SIGKILL);
|
||||
} else {
|
||||
LOG_ERROR("sigtimedwait failed: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
_exit(EXIT_SUCCESS);
|
||||
break;
|
||||
}
|
||||
|
||||
close(pipes[1]);
|
||||
if (read(pipes[0], buffer, EXTERNAL_BUFFER_MAX) < 0) {
|
||||
if (read(pipes[0], internal, EXTERNAL_BUFFER_MAX) < 0) {
|
||||
LOG_ERROR("Failed to read from process %s: %s\n", exec_args[0], strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
@ -126,9 +131,13 @@ int run_external_process_get_output(const char *const *exec_args, char buffer[EX
|
||||
if (!WIFEXITED(status)) {
|
||||
LOG_ERROR("Child process '%s' exited abnormally\n", exec_args[0]);
|
||||
} else if (WEXITSTATUS(status) != 0) {
|
||||
LOG_ERROR("External process failed\n");
|
||||
LOG_ERROR("External process failed with exit code %u\n", WEXITSTATUS(status));
|
||||
LOG_ERROR("Output was: %s\n", buffer ? buffer : internal);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (buffer)
|
||||
memcpy(buffer, internal, EXTERNAL_BUFFER_MAX);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -34,7 +34,4 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
#define EXTERNAL_BUFFER_MAX 1024
|
||||
|
||||
/* Run an external process and capture the return value */
|
||||
int run_external_process(const char *const *exec_args);
|
||||
|
||||
/* Run an external process and capture the return value as well as output */
|
||||
int run_external_process_get_output(const char *const *exec_args, char buffer[EXTERNAL_BUFFER_MAX]);
|
||||
int run_external_process(const char *const *exec_args, char buffer[EXTERNAL_BUFFER_MAX], int tsec);
|
||||
|
@ -229,7 +229,7 @@ int game_mode_apply_gpu(const GameModeGPUInfo *info, bool apply)
|
||||
NULL,
|
||||
};
|
||||
|
||||
if (run_external_process(exec_args) != 0) {
|
||||
if (run_external_process(exec_args, NULL, -1) != 0) {
|
||||
LOG_ERROR("Failed to call gpuclockctl, could not apply optimisations!\n");
|
||||
return -1;
|
||||
}
|
||||
@ -262,7 +262,7 @@ int game_mode_get_gpu(GameModeGPUInfo *info)
|
||||
};
|
||||
|
||||
char buffer[EXTERNAL_BUFFER_MAX] = { 0 };
|
||||
if (run_external_process_get_output(exec_args, buffer) != 0) {
|
||||
if (run_external_process(exec_args, buffer, -1) != 0) {
|
||||
LOG_ERROR("Failed to call gpuclockctl, could get values!\n");
|
||||
return -1;
|
||||
}
|
||||
|
@ -41,27 +41,45 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <unistd.h>
|
||||
|
||||
#include "daemon_config.h"
|
||||
#include "external-helper.h"
|
||||
#include "gamemode_client.h"
|
||||
#include "governors-query.h"
|
||||
#include "gpu-control.h"
|
||||
|
||||
/* Initial verify step to ensure gamemode isn't already active */
|
||||
static int verify_gamemode_initial(void)
|
||||
static int verify_gamemode_initial(struct GameModeConfig *config)
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
if ((status = gamemode_query_status()) != 0 && status != -1) {
|
||||
LOG_ERROR("gamemode is currently active, tests require gamemode to start deactivated!\n");
|
||||
status = -1;
|
||||
long reaper = config_get_reaper_frequency(config);
|
||||
LOG_MSG("GameMode was active, waiting for the reaper thread (%ld seconds)!\n", reaper);
|
||||
sleep(1);
|
||||
|
||||
/* Try again after waiting */
|
||||
for (int i = 0; i < reaper; i++) {
|
||||
if ((status = gamemode_query_status()) == 0) {
|
||||
status = 0;
|
||||
break;
|
||||
} else if (status == -1) {
|
||||
goto status_error;
|
||||
}
|
||||
LOG_MSG("Waiting...\n");
|
||||
sleep(1);
|
||||
}
|
||||
if (status == 1)
|
||||
LOG_ERROR("GameMode still active, cannot run tests!\n");
|
||||
} else if (status == -1) {
|
||||
LOG_ERROR("gamemode_query_status failed: %s!\n", gamemode_error_string());
|
||||
LOG_ERROR("is gamemode installed correctly?\n");
|
||||
status = -1;
|
||||
goto status_error;
|
||||
} else {
|
||||
status = 0;
|
||||
}
|
||||
|
||||
return status;
|
||||
status_error:
|
||||
LOG_ERROR("gamemode_query_status failed: %s!\n", gamemode_error_string());
|
||||
LOG_ERROR("is gamemode installed correctly?\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check if gamemode is active and this client is registered */
|
||||
@ -183,8 +201,8 @@ static int run_dual_client_tests(void)
|
||||
/* Parent process */
|
||||
/* None of these should early-out as we need to clean up the child */
|
||||
|
||||
/* Give the child a chance to reqeust gamemode */
|
||||
usleep(1000);
|
||||
/* Give the child a chance to request gamemode */
|
||||
usleep(10000);
|
||||
|
||||
/* Check that when we request gamemode, it replies that the other client is connected */
|
||||
if (verify_other_client_connected() != 0)
|
||||
@ -301,12 +319,11 @@ static int run_cpu_governor_tests(struct GameModeConfig *config)
|
||||
strcpy(desiredgov, "performance");
|
||||
|
||||
char defaultgov[CONFIG_VALUE_MAX] = { 0 };
|
||||
config_get_default_governor(config, defaultgov);
|
||||
|
||||
if (desiredgov[0] == '\0') {
|
||||
if (defaultgov[0] == '\0') {
|
||||
const char *currentgov = get_gov_state();
|
||||
if (currentgov) {
|
||||
strncpy(desiredgov, currentgov, CONFIG_VALUE_MAX);
|
||||
strncpy(defaultgov, currentgov, CONFIG_VALUE_MAX);
|
||||
} else {
|
||||
LOG_ERROR(
|
||||
"Could not get current CPU governor state, this indicates an error! See rest "
|
||||
@ -342,6 +359,7 @@ static int run_cpu_governor_tests(struct GameModeConfig *config)
|
||||
static int run_custom_scripts_tests(struct GameModeConfig *config)
|
||||
{
|
||||
int scriptstatus = 0;
|
||||
long timeout = config_get_script_timeout(config);
|
||||
|
||||
/* Grab and test the start scripts */
|
||||
char startscripts[CONFIG_LIST_MAX][CONFIG_VALUE_MAX];
|
||||
@ -353,7 +371,8 @@ static int run_custom_scripts_tests(struct GameModeConfig *config)
|
||||
while (*startscripts[i] != '\0' && i < CONFIG_LIST_MAX) {
|
||||
LOG_MSG(":::: Running start script [%s]\n", startscripts[i]);
|
||||
|
||||
int ret = system(startscripts[i]);
|
||||
const char *args[] = { "/bin/sh", "-c", startscripts[i], NULL };
|
||||
int ret = run_external_process(args, NULL, (int)timeout);
|
||||
|
||||
if (ret == 0)
|
||||
LOG_MSG(":::: Passed\n");
|
||||
@ -375,7 +394,8 @@ static int run_custom_scripts_tests(struct GameModeConfig *config)
|
||||
while (*endscripts[i] != '\0' && i < CONFIG_LIST_MAX) {
|
||||
LOG_MSG(":::: Running end script [%s]\n", endscripts[i]);
|
||||
|
||||
int ret = system(endscripts[i]);
|
||||
const char *args[] = { "/bin/sh", "-c", endscripts[i], NULL };
|
||||
int ret = run_external_process(args, NULL, (int)timeout);
|
||||
|
||||
if (ret == 0)
|
||||
LOG_MSG(":::: Passed\n");
|
||||
@ -668,7 +688,7 @@ int game_mode_run_client_tests()
|
||||
/* First verify that gamemode is not currently active on the system
|
||||
* As well as it being currently installed and queryable
|
||||
*/
|
||||
if (verify_gamemode_initial() != 0)
|
||||
if (verify_gamemode_initial(config) != 0)
|
||||
return -1;
|
||||
|
||||
/* Controls whether we require a supervisor to actually make requests */
|
||||
|
@ -93,6 +93,7 @@ static void *game_mode_context_reaper(void *userdata);
|
||||
static void game_mode_context_enter(GameModeContext *self);
|
||||
static void game_mode_context_leave(GameModeContext *self);
|
||||
static char *game_mode_context_find_exe(pid_t pid);
|
||||
static void game_mode_execute_scripts(char scripts[CONFIG_LIST_MAX][CONFIG_VALUE_MAX], int timeout);
|
||||
|
||||
void game_mode_context_init(GameModeContext *self)
|
||||
{
|
||||
@ -170,21 +171,6 @@ static void game_mode_context_enter(GameModeContext *self)
|
||||
LOG_MSG("Entering Game Mode...\n");
|
||||
sd_notifyf(0, "STATUS=%sGameMode is now active.%s\n", "\x1B[1;32m", "\x1B[0m");
|
||||
|
||||
char scripts[CONFIG_LIST_MAX][CONFIG_VALUE_MAX];
|
||||
memset(scripts, 0, sizeof(scripts));
|
||||
config_get_gamemode_start_scripts(self->config, scripts);
|
||||
|
||||
unsigned int i = 0;
|
||||
while (*scripts[i] != '\0' && i < CONFIG_LIST_MAX) {
|
||||
LOG_MSG("Executing script [%s]\n", scripts[i]);
|
||||
int err;
|
||||
if ((err = system(scripts[i])) != 0) {
|
||||
/* Log the failure, but this is not fatal */
|
||||
LOG_ERROR("Script [%s] failed with error %d\n", scripts[i], err);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Read the initial governor state so we can revert it correctly */
|
||||
const char *initial_state = get_gov_state();
|
||||
if (initial_state) {
|
||||
@ -203,7 +189,7 @@ static void game_mode_context_enter(GameModeContext *self)
|
||||
};
|
||||
|
||||
LOG_MSG("Requesting update of governor policy to %s\n", desiredGov);
|
||||
if (run_external_process(exec_args) != 0) {
|
||||
if (run_external_process(exec_args, NULL, -1) != 0) {
|
||||
LOG_ERROR("Failed to update cpu governor policy\n");
|
||||
/* if the set fails, clear the initial mode so we don't try and reset it back and fail
|
||||
* again, presumably */
|
||||
@ -217,6 +203,14 @@ static void game_mode_context_enter(GameModeContext *self)
|
||||
|
||||
/* Apply GPU optimisations */
|
||||
game_mode_apply_gpu(self->gpu_info, true);
|
||||
|
||||
/* Run custom scripts last - ensures the above are applied first and these scripts can react to
|
||||
* them if needed */
|
||||
char scripts[CONFIG_LIST_MAX][CONFIG_VALUE_MAX];
|
||||
memset(scripts, 0, sizeof(scripts));
|
||||
config_get_gamemode_start_scripts(self->config, scripts);
|
||||
long timeout = config_get_script_timeout(self->config);
|
||||
game_mode_execute_scripts(scripts, (int)timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -249,7 +243,7 @@ static void game_mode_context_leave(GameModeContext *self)
|
||||
};
|
||||
|
||||
LOG_MSG("Requesting update of governor policy to %s\n", gov_mode);
|
||||
if (run_external_process(exec_args) != 0) {
|
||||
if (run_external_process(exec_args, NULL, -1) != 0) {
|
||||
LOG_ERROR("Failed to update cpu governor policy\n");
|
||||
}
|
||||
|
||||
@ -259,17 +253,8 @@ static void game_mode_context_leave(GameModeContext *self)
|
||||
char scripts[CONFIG_LIST_MAX][CONFIG_VALUE_MAX];
|
||||
memset(scripts, 0, sizeof(scripts));
|
||||
config_get_gamemode_end_scripts(self->config, scripts);
|
||||
|
||||
unsigned int i = 0;
|
||||
while (*scripts[i] != '\0' && i < CONFIG_LIST_MAX) {
|
||||
LOG_MSG("Executing script [%s]\n", scripts[i]);
|
||||
int err;
|
||||
if ((err = system(scripts[i])) != 0) {
|
||||
/* Log the failure, but this is not fatal */
|
||||
LOG_ERROR("Script [%s] failed with error %d\n", scripts[i], err);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
long timeout = config_get_script_timeout(self->config);
|
||||
game_mode_execute_scripts(scripts, (int)timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -701,3 +686,19 @@ fail:
|
||||
LOG_ERROR("Unable to find executable for PID %d: %s\n", pid, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Executes a set of scripts */
|
||||
static void game_mode_execute_scripts(char scripts[CONFIG_LIST_MAX][CONFIG_VALUE_MAX], int timeout)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
while (*scripts[i] != '\0' && i < CONFIG_LIST_MAX) {
|
||||
LOG_MSG("Executing script [%s]\n", scripts[i]);
|
||||
int err;
|
||||
const char *args[] = { "/bin/sh", "-c", scripts[i], NULL };
|
||||
if ((err = run_external_process(args, NULL, timeout)) != 0) {
|
||||
/* Log the failure, but this is not fatal */
|
||||
LOG_ERROR("Script [%s] failed with error %d\n", scripts[i], err);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ static int get_gpu_state_nv(struct GameModeGPUInfo *info)
|
||||
NV_CORE_OFFSET_ATTRIBUTE,
|
||||
info->nv_perf_level);
|
||||
const char *exec_args_core[] = { "/usr/bin/nvidia-settings", "-q", arg, "-t", NULL };
|
||||
if (run_external_process_get_output(exec_args_core, buf) != 0) {
|
||||
if (run_external_process(exec_args_core, buf, -1) != 0) {
|
||||
LOG_ERROR("Failed to set %s!\n", arg);
|
||||
return -1;
|
||||
}
|
||||
@ -98,7 +98,7 @@ static int get_gpu_state_nv(struct GameModeGPUInfo *info)
|
||||
NV_MEM_OFFSET_ATTRIBUTE,
|
||||
info->nv_perf_level);
|
||||
const char *exec_args_mem[] = { "/usr/bin/nvidia-settings", "-q", arg, "-t", NULL };
|
||||
if (run_external_process_get_output(exec_args_mem, buf) != 0) {
|
||||
if (run_external_process(exec_args_mem, buf, -1) != 0) {
|
||||
LOG_ERROR("Failed to set %s!\n", arg);
|
||||
return -1;
|
||||
}
|
||||
@ -145,7 +145,7 @@ static int set_gpu_state_nv(struct GameModeGPUInfo *info)
|
||||
info->nv_perf_level,
|
||||
info->core);
|
||||
const char *exec_args_core[] = { "/usr/bin/nvidia-settings", "-a", core_arg, NULL };
|
||||
if (run_external_process(exec_args_core) != 0) {
|
||||
if (run_external_process(exec_args_core, NULL, -1) != 0) {
|
||||
LOG_ERROR("Failed to set %s!\n", core_arg);
|
||||
return -1;
|
||||
}
|
||||
@ -160,7 +160,7 @@ static int set_gpu_state_nv(struct GameModeGPUInfo *info)
|
||||
info->nv_perf_level,
|
||||
info->mem);
|
||||
const char *exec_args_mem[] = { "/usr/bin/nvidia-settings", "-a", mem_arg, NULL };
|
||||
if (run_external_process(exec_args_mem) != 0) {
|
||||
if (run_external_process(exec_args_mem, NULL, -1) != 0) {
|
||||
LOG_ERROR("Failed to set %s!\n", mem_arg);
|
||||
return -1;
|
||||
}
|
||||
|
@ -47,6 +47,8 @@ static int gamemode_request(const char *function, int arg)
|
||||
{
|
||||
sd_bus_message *msg = NULL;
|
||||
sd_bus *bus = NULL;
|
||||
sd_bus_error err;
|
||||
memset(&err, 0, sizeof(err));
|
||||
|
||||
int result = -1;
|
||||
|
||||
@ -64,7 +66,7 @@ static int gamemode_request(const char *function, int arg)
|
||||
"/com/feralinteractive/GameMode",
|
||||
"com.feralinteractive.GameMode",
|
||||
function,
|
||||
NULL,
|
||||
&err,
|
||||
&msg,
|
||||
arg ? "ii" : "i",
|
||||
getpid(),
|
||||
@ -72,7 +74,13 @@ static int gamemode_request(const char *function, int arg)
|
||||
if (ret < 0) {
|
||||
snprintf(error_string,
|
||||
sizeof(error_string),
|
||||
"Could not call method on bus: %s",
|
||||
"Could not call method %s on com.feralinteractive.GameMode\n"
|
||||
"\t%s\n"
|
||||
"\t%s\n"
|
||||
"\t%s\n",
|
||||
function,
|
||||
err.name,
|
||||
err.message,
|
||||
strerror(-ret));
|
||||
} else {
|
||||
// Read the reply
|
||||
|
Loading…
x
Reference in New Issue
Block a user