From: Simon McVittie Date: Mon, 21 Feb 2022 15:41:41 +0000 (+0000) Subject: sysdeps-unix: Factor out _dbus_reset_oom_score_adj X-Git-Tag: dbus-1.13.22~2^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f3ffe9a873708c679df88b9fc12b6b831539cf8a;p=thirdparty%2Fdbus.git sysdeps-unix: Factor out _dbus_reset_oom_score_adj Signed-off-by: Simon McVittie --- diff --git a/dbus/dbus-spawn-unix.c b/dbus/dbus-spawn-unix.c index 6a888eb57..eecc3219b 100644 --- a/dbus/dbus-spawn-unix.c +++ b/dbus/dbus-spawn-unix.c @@ -1444,26 +1444,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 e86de6d94..a051b5429 100644 --- a/dbus/dbus-sysdeps-unix.h +++ b/dbus/dbus-sysdeps-unix.h @@ -174,6 +174,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 878ca2eaa..799c6892a 100644 --- a/dbus/dbus-sysdeps-util-unix.c +++ b/dbus/dbus-sysdeps-util-unix.c @@ -1603,3 +1603,68 @@ _dbus_daemon_report_stopping (void) sd_notify (0, "STOPPING=1"); #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 +}