summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon McVittie <smcv@collabora.com>2022-02-21 15:41:41 +0000
committerSimon McVittie <smcv@collabora.com>2022-02-25 14:57:18 +0000
commit7200555694ed614cc91ddbc5dd17805f7d6d4111 (patch)
tree7ec825c8232d978df2411a76dd5f2fde91c4bf99
parent0e4b432f71e20aa7b606125b5d530e9669adffd1 (diff)
downloaddbus-7200555694ed614cc91ddbc5dd17805f7d6d4111.tar.gz
sysdeps-unix: Factor out _dbus_reset_oom_score_adj
Signed-off-by: Simon McVittie <smcv@collabora.com> (cherry picked from commit f3ffe9a873708c679df88b9fc12b6b831539cf8a)
-rw-r--r--dbus/dbus-spawn.c20
-rw-r--r--dbus/dbus-sysdeps-unix.h2
-rw-r--r--dbus/dbus-sysdeps-util-unix.c65
3 files changed, 71 insertions, 16 deletions
diff --git a/dbus/dbus-spawn.c b/dbus/dbus-spawn.c
index 61c7e619..b4aff676 100644
--- a/dbus/dbus-spawn.c
+++ b/dbus/dbus-spawn.c
@@ -1397,26 +1397,14 @@ _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p,
}
else if (grandchild_pid == 0)
{
-#ifdef __linux__
- int fd = -1;
+ const char *error_str = NULL;
-#ifdef O_CLOEXEC
- fd = open ("/proc/self/oom_score_adj", O_WRONLY | O_CLOEXEC);
-#endif
-
- if (fd < 0)
+ if (!_dbus_reset_oom_score_adj (&error_str))
{
- fd = open ("/proc/self/oom_score_adj", O_WRONLY);
- _dbus_fd_set_close_on_exec (fd);
+ /* TODO: Strictly speaking, this is not async-signal-safe. */
+ _dbus_warn ("%s: %s", error_str, strerror (errno));
}
- if (fd >= 0)
- {
- if (write (fd, "0", sizeof (char)) < 0)
- _dbus_warn ("writing oom_score_adj error: %s", strerror (errno));
- _dbus_close (fd, NULL);
- }
-#endif
/* Go back to ignoring SIGPIPE, since it's evil
*/
signal (SIGPIPE, SIG_IGN);
diff --git a/dbus/dbus-sysdeps-unix.h b/dbus/dbus-sysdeps-unix.h
index 830d5cd0..5de8b731 100644
--- a/dbus/dbus-sysdeps-unix.h
+++ b/dbus/dbus-sysdeps-unix.h
@@ -173,6 +173,8 @@ typedef void (* DBusSignalHandler) (int sig);
void _dbus_set_signal_handler (int sig,
DBusSignalHandler handler);
+dbus_bool_t _dbus_reset_oom_score_adj (const char **error_str_p);
+
/** @} */
DBUS_END_DECLS
diff --git a/dbus/dbus-sysdeps-util-unix.c b/dbus/dbus-sysdeps-util-unix.c
index cc7bbe62..dcf6dcff 100644
--- a/dbus/dbus-sysdeps-util-unix.c
+++ b/dbus/dbus-sysdeps-util-unix.c
@@ -1571,3 +1571,68 @@ _dbus_test_append_different_username (DBusString *username)
}
#endif
+
+/**
+ * If the current process has been protected from the Linux OOM killer
+ * (the oom_score_adj process parameter is negative), reset it to the
+ * default level of protection from the OOM killer (set oom_score_adj
+ * to zero).
+ *
+ * This function does not use DBusError, to avoid calling malloc(), so
+ * that it can be used in contexts where an async-signal-safe function
+ * is required (for example after fork()). Instead, on failure it sets
+ * errno and returns something like "Failed to open /dev/null" in
+ * *error_str_p. Callers are expected to combine *error_str_p
+ * with _dbus_strerror (errno) to get a full error report.
+ */
+dbus_bool_t
+_dbus_reset_oom_score_adj (const char **error_str_p)
+{
+#ifdef __linux__
+ int fd = -1;
+ dbus_bool_t ret = FALSE;
+ int saved_errno = 0;
+ const char *error_str = NULL;
+
+#ifdef O_CLOEXEC
+ fd = open ("/proc/self/oom_score_adj", O_WRONLY | O_CLOEXEC);
+#endif
+
+ if (fd < 0)
+ {
+ fd = open ("/proc/self/oom_score_adj", O_WRONLY);
+ _dbus_fd_set_close_on_exec (fd);
+ }
+
+ if (fd >= 0)
+ {
+ if (write (fd, "0", sizeof (char)) < 0)
+ {
+ ret = FALSE;
+ error_str = "writing oom_score_adj error";
+ saved_errno = errno;
+ }
+ else
+ {
+ ret = TRUE;
+ }
+
+ _dbus_close (fd, NULL);
+ }
+ else
+ {
+ /* TODO: Historically we ignored this error, although ideally we
+ * would diagnose it */
+ ret = TRUE;
+ }
+
+ if (error_str_p != NULL)
+ *error_str_p = error_str;
+
+ errno = saved_errno;
+ return ret;
+#else
+ /* nothing to do on this platform */
+ return TRUE;
+#endif
+}