shared: add a common SIGRTMIN-18 handler
This commit is contained in:
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user