Set up for resetting niceness value

Add tests to check this feature
	Apply config validation in config for simplicity

	Note: if anything messes with the niceness (ie. it starts non-zero, or it's not the expected value during setup, we'll bail out)
This commit is contained in:
Marc Di Luzio
2019-05-11 10:33:29 +01:00
parent 7e5216c4a0
commit 09d63ae4f5
5 changed files with 118 additions and 17 deletions

View File

@ -54,13 +54,28 @@ POSSIBILITY OF SUCH DAMAGE.
* This tries to change the scheduler of the client to soft realtime mode
* available in some kernels as SCHED_ISO. It also tries to adjust the nice
* level. If some of each fail, ignore this and log a warning.
*
* We don't need to store the current values because when the client exits,
* everything will be good: Scheduling is only applied to the client and
* its children.
*/
void game_mode_apply_renice(const GameModeContext *self, const pid_t client)
#define RENICE_INVALID -128 /* Special value to store invalid value */
int game_mode_get_renice(const pid_t client)
{
/* Clear errno as -1 is a regitimate return */
errno = 0;
int priority = getpriority(PRIO_PROCESS, (id_t)client);
if (priority == -1 && errno) {
LOG_ERROR("getprority(PRIO_PROCESS, %d) failed : %s\n", client, strerror(errno));
return RENICE_INVALID;
}
return -priority;
}
/* If expected is 0 then we try to apply our renice, otherwise, we try to remove it */
void game_mode_apply_renice(const GameModeContext *self, const pid_t client, int expected)
{
if (expected == RENICE_INVALID)
/* Silently bail if fed an invalid value */
return;
GameModeConfig *config = game_mode_config_from_context(self);
/*
@ -69,18 +84,35 @@ void game_mode_apply_renice(const GameModeContext *self, const pid_t client)
long int renice = config_get_renice_value(config);
if (renice == 0) {
return;
} else if ((renice < 1) || (renice > 20)) {
LOG_ONCE(ERROR, "Configured renice value '%ld' is invalid, will not renice.\n", renice);
return;
} else {
renice = -renice;
}
/*
* don't adjust priority if it was already adjusted
*/
if (getpriority(PRIO_PROCESS, (id_t)client) != 0) {
LOG_ERROR("Refused to renice client [%d]: already reniced\n", client);
/* Invert the renice value */
renice = -renice;
/* When expected is non-zero, we should try and remove the renice only if it doesn't match the
* expected value */
if (expected != 0) {
expected = (int)renice;
renice = 0;
}
/* Clear errno as -1 is a regitimate return */
errno = 0;
int prio = getpriority(PRIO_PROCESS, (id_t)client);
if (prio == -1 && errno) {
/* process has likely ended, only log an error if we were actually trying to set a non-zero
* value */
if (errno == ESRCH && renice != 0)
LOG_ERROR("getpriority returned ESRCH for process %d\n", client);
} else if (prio != expected) {
/*
* Don't adjust priority if it does not match the expected value
* ie. Another process has changed it, or it began non-standard
*/
LOG_ERROR("Refused to renice client [%d]: prio was (%d) but we expected (%d)\n",
client,
prio,
expected);
} else if (setpriority(PRIO_PROCESS, (id_t)client, (int)renice)) {
LOG_HINTED(ERROR,
"Failed to renice client [%d], ignoring error condition: %s\n",