Explorar o código

gamemode-scheduler: Improve logging

During finding the cause of an issue, we discovered bad interactions
with other resource management daemon that may be running at the same
time and may interfere with GameMode's ability to properly set
scheduling parameters of the process. Usually, this results in EPERM
(instead of EINVAL for lacking kernel support). It also means that the
other daemon is leaking wrong scheduling settings into the games with
negative performance impacts (quite the opposite of what the user wanted
to achieve). So we should give some valuable hints.

This commit improves logging by detecting the error situation and giving
context-based hints on what to do next. To keep logging verbosity low,
the hint is only logged once per error code.

Closes: https://github.com/FeralInteractive/gamemode/issues/68
Signed-off-by: Kai Krakow <kai@kaishome.de>
Kai Krakow %!s(int64=6) %!d(string=hai) anos
pai
achega
8a618a29fa
Modificáronse 1 ficheiros con 43 adicións e 11 borrados
  1. 43 11
      daemon/gamemode.c

+ 43 - 11
daemon/gamemode.c

@@ -184,15 +184,15 @@ void game_mode_context_destroy(GameModeContext *self)
  */
 static void game_mode_apply_scheduler(GameModeContext *self, pid_t client)
 {
-	LOG_MSG("Setting scheduling policies...\n");
-
 	/*
 	 * read configuration "renice" (1..20)
 	 */
 	long int renice = 0;
 	config_get_renice_value(self->config, &renice);
 	if ((renice < 1) || (renice > 20)) {
-		LOG_ERROR("Renice value [%ld] defaulted to [%d].\n", renice, -NICE_DEFAULT_PRIORITY);
+		LOG_ERROR("Invalid renice value '%ld' reset to default: %d.\n",
+		          renice,
+		          -NICE_DEFAULT_PRIORITY);
 		renice = NICE_DEFAULT_PRIORITY;
 	} else {
 		renice = -renice;
@@ -202,13 +202,14 @@ static void game_mode_apply_scheduler(GameModeContext *self, pid_t client)
 	 * don't adjust priority if it was already adjusted
 	 */
 	if (getpriority(PRIO_PROCESS, (id_t)client) != 0) {
-		LOG_ERROR("Client [%d] already reniced, ignoring.\n", client);
+		LOG_ERROR("Refused to renice client [%d]: already reniced\n", client);
 	} else if (setpriority(PRIO_PROCESS, (id_t)client, (int)renice)) {
 		LOG_ERROR(
-		    "Renicing client [%d] failed with error %d, ignoring (your user may not have "
-		    "permission to do this).\n",
+		    "Failed to renice client [%d], ignoring error condition: %s\n"
+		    "    -- Your user may not have permission to do this. Please read the docs\n"
+		    "    -- to learn how to adjust the pam limits.\n",
 		    client,
-		    errno);
+		    strerror(errno));
 	}
 
 	/*
@@ -231,14 +232,45 @@ static void game_mode_apply_scheduler(GameModeContext *self, pid_t client)
 	if (!(strcmp(softrealtime, "off") == 0) && (enable_softrealtime)) {
 		const struct sched_param p = { .sched_priority = 0 };
 		if (sched_setscheduler(client, SCHED_ISO | SCHED_RESET_ON_FORK, &p)) {
+			const char *additional_message = "";
+			switch (errno) {
+			case EPERM: {
+				static int once = 0;
+				if (once++)
+					break;
+				additional_message =
+				    "    -- The error indicates that you may be running a resource management\n"
+				    "    -- daemon managing your game launcher and it leaks lower scheduling\n"
+				    "    -- classes into the games. This is likely a bug in the management daemon\n"
+				    "    -- and not a bug in GameMode, it should be reported upstream.\n"
+				    "    -- If unsure, please also look here:\n"
+				    "    -- https://github.com/FeralInteractive/gamemode/issues/68\n";
+				break;
+			}
+			case EINVAL: {
+				static int once = 0;
+				if (once++)
+					break;
+				additional_message =
+				    "    -- The error indicates that your kernel may not support this. If you\n"
+				    "    -- don't know what SCHED_ISO means, you can safely ignore this. If you\n"
+				    "    -- expected it to work, ensure you're running a kernel with MuQSS or\n"
+				    "    -- PDS scheduler.\n"
+				    "    -- For further technical reading on the topic start here:\n"
+				    "    -- https://lwn.net/Articles/720227/\n";
+				break;
+			}
+			}
 			LOG_ERROR(
-			    "Setting client [%d] to SCHED_ISO failed with error %d, ignoring (your "
-			    "kernel may not support this).\n",
+			    "Failed setting client [%d] into SCHED_ISO mode, ignoring error condition: %s\n%s",
 			    client,
-			    errno);
+			    strerror(errno),
+			    additional_message);
 		}
 	} else {
-		LOG_ERROR("Not using softrealtime, setting is '%s'.\n", softrealtime);
+		LOG_ERROR("Skipped setting client [%d] into SCHED_ISO mode: softrealtime setting is '%s'\n",
+		          client,
+		          softrealtime);
 	}
 }