shared: add a common SIGRTMIN-18 handler

This commit is contained in:
Lennart Poettering
2023-03-01 09:43:23 +01:00
parent 45db7b53e7
commit 9b2c161481
3 changed files with 153 additions and 0 deletions
+94
View File
@@ -0,0 +1,94 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "common-signal.h"
#include "fd-util.h"
#include "fileio.h"
#include "process-util.h"
#include "signal-util.h"
int sigrtmin18_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
struct sigrtmin18_info *info = userdata;
_cleanup_free_ char *comm = NULL;
int r;
assert(s);
assert(si);
(void) get_process_comm(si->ssi_pid, &comm);
if (si->ssi_code != SI_QUEUE) {
log_notice("Received control signal %s from process " PID_FMT " (%s) without command value, ignoring.",
signal_to_string(si->ssi_signo),
(pid_t) si->ssi_pid,
strna(comm));
return 0;
}
log_debug("Received control signal %s from process " PID_FMT " (%s) with command 0x%08x.",
signal_to_string(si->ssi_signo),
(pid_t) si->ssi_pid,
strna(comm),
(unsigned) si->ssi_int);
switch (si->ssi_int) {
case _COMMON_SIGNAL_COMMAND_LOG_LEVEL_BASE..._COMMON_SIGNAL_COMMAND_LOG_LEVEL_END:
log_set_max_level(si->ssi_int - _COMMON_SIGNAL_COMMAND_LOG_LEVEL_BASE);
break;
case COMMON_SIGNAL_COMMAND_CONSOLE:
log_set_target_and_open(LOG_TARGET_CONSOLE);
break;
case COMMON_SIGNAL_COMMAND_JOURNAL:
log_set_target_and_open(LOG_TARGET_JOURNAL);
break;
case COMMON_SIGNAL_COMMAND_KMSG:
log_set_target_and_open(LOG_TARGET_KMSG);
break;
case COMMON_SIGNAL_COMMAND_NULL:
log_set_target_and_open(LOG_TARGET_NULL);
break;
case COMMON_SIGNAL_COMMAND_MEMORY_PRESSURE:
if (info && info->memory_pressure_handler)
return info->memory_pressure_handler(s, info->memory_pressure_userdata);
sd_event_trim_memory();
break;
case COMMON_SIGNAL_COMMAND_MALLOC_INFO: {
_cleanup_free_ char *data = NULL;
_cleanup_fclose_ FILE *f = NULL;
size_t sz;
f = open_memstream_unlocked(&data, &sz);
if (!f) {
log_oom();
break;
}
if (malloc_info(0, f) < 0) {
log_error_errno(errno, "Failed to invoke malloc_info(): %m");
break;
}
fputc(0, f);
r = fflush_and_check(f);
if (r < 0) {
log_error_errno(r, "Failed to flush malloc_info() buffer: %m");
break;
}
log_dump(LOG_INFO, data);
break;
}
default:
log_notice("Received control signal %s with unknown command 0x%08x, ignoring.",
signal_to_string(si->ssi_signo), (unsigned) si->ssi_int);
break;
}
return 0;
}
+58
View File
@@ -0,0 +1,58 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <syslog.h>
#include <sd-event.h>
/* All our long-running services should implement a SIGRTMIN+18 handler that can be used to trigger certain
* actions that affect service runtime. The specific action is indicated via the "value integer" you can pass
* along realtime signals. This is mostly intended for debugging purposes and is entirely asynchronous in
* nature. Specifically, these are the commands:
*
* Currently available operations:
*
* • Change maximum log level
* • Change log target
* • Invoke memory trimming, like under memory pressure
* • Write glibc malloc() allocation info to logs
*
* How to use this? Via a command like the following:
*
* /usr/bin/kill -s RTMIN+18 -q 768 1
*
* (This will tell PID 1 to trim its memory use.)
*
* or:
*
* systemctl kill --kill-value=0x300 -s RTMIN+18 systemd-journald
*
* (This will tell journald to trim its memory use.)
*/
enum {
_COMMON_SIGNAL_COMMAND_LOG_LEVEL_BASE = 0x100,
COMMON_SIGNAL_COMMAND_LOG_EMERG = _COMMON_SIGNAL_COMMAND_LOG_LEVEL_BASE + LOG_EMERG,
COMMON_SIGNAL_COMMAND_LOG_ALERT = _COMMON_SIGNAL_COMMAND_LOG_LEVEL_BASE + LOG_ALERT,
COMMON_SIGNAL_COMMAND_LOG_CRIT = _COMMON_SIGNAL_COMMAND_LOG_LEVEL_BASE + LOG_CRIT,
COMMON_SIGNAL_COMMAND_LOG_ERR = _COMMON_SIGNAL_COMMAND_LOG_LEVEL_BASE + LOG_ERR,
COMMON_SIGNAL_COMMAND_LOG_WARNING = _COMMON_SIGNAL_COMMAND_LOG_LEVEL_BASE + LOG_WARNING,
COMMON_SIGNAL_COMMAND_LOG_NOTICE = _COMMON_SIGNAL_COMMAND_LOG_LEVEL_BASE + LOG_NOTICE,
COMMON_SIGNAL_COMMAND_LOG_INFO = _COMMON_SIGNAL_COMMAND_LOG_LEVEL_BASE + LOG_INFO,
COMMON_SIGNAL_COMMAND_LOG_DEBUG = _COMMON_SIGNAL_COMMAND_LOG_LEVEL_BASE + LOG_DEBUG,
_COMMON_SIGNAL_COMMAND_LOG_LEVEL_END = COMMON_SIGNAL_COMMAND_LOG_DEBUG,
COMMON_SIGNAL_COMMAND_CONSOLE = 0x200,
COMMON_SIGNAL_COMMAND_JOURNAL,
COMMON_SIGNAL_COMMAND_KMSG,
COMMON_SIGNAL_COMMAND_NULL,
COMMON_SIGNAL_COMMAND_MEMORY_PRESSURE = 0x300,
COMMON_SIGNAL_COMMAND_MALLOC_INFO,
};
struct sigrtmin18_info {
sd_event_handler_t memory_pressure_handler;
void *memory_pressure_userdata;
};
int sigrtmin18_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata);
+1
View File
@@ -35,6 +35,7 @@ shared_sources = files(
'chown-recursive.c',
'clean-ipc.c',
'clock-util.c',
'common-signal.c',
'compare-operator.c',
'condition.c',
'conf-parser.c',