1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2025-02-08 05:57:26 +03:00

core: Settle log target if we're going to be closing all fds

Whenever we're going to close all file descriptors, we tend to close
the log and set it into open when needed mode. When this is done with
the logging target set to LOG_TARGET_AUTO, we run into issues because
for every logging call, we'll check if stderr is connected to the
journal to determine where to send the logging message. This check
obviously stops working when we close stderr, so we settle the log
target before we do that so that we keep using the same logging
target even after stderr is closed.

(cherry picked from commit a3b00f91bb985fa10bc33db5c7883e33dbdf83d0)
(cherry picked from commit 22c47d24a447112bbf8022a79d9c3940a2f04316)
(cherry picked from commit dc92016bd7d58a0f264323d1150fdc9253888418)
This commit is contained in:
Daan De Meyer 2023-03-20 13:26:57 +01:00 committed by Zbigniew Jędrzejewski-Szmek
parent 076f1d3328
commit 910d8794d8
7 changed files with 25 additions and 0 deletions

View File

@ -79,6 +79,8 @@ static int open_sockets(int *epoll_fd, bool accept) {
except[i] = SD_LISTEN_FDS_START + i;
log_close();
log_settle_target();
r = close_all_fds(except, n);
if (r < 0)
return log_error_errno(r, "Failed to close all file descriptors: %m");

View File

@ -1235,6 +1235,24 @@ LogTarget log_get_target(void) {
return log_target;
}
void log_settle_target(void) {
/* If we're using LOG_TARGET_AUTO and opening the log again on every single log call, we'll check if
* stderr is attached to the journal every single log call. However, if we then close all file
* descriptors later, that will stop working because stderr will be closed as well. To avoid that
* problem, this function is used to permanently change the log target depending on whether stderr is
* connected to the journal or not. */
LogTarget t = log_get_target();
if (t != LOG_TARGET_AUTO)
return;
t = getpid_cached() == 1 || stderr_is_journal() ? (prohibit_ipc ? LOG_TARGET_KMSG : LOG_TARGET_JOURNAL_OR_KMSG)
: LOG_TARGET_CONSOLE;
log_set_target(t);
}
int log_get_max_level(void) {
return log_max_level;
}

View File

@ -50,6 +50,7 @@ LogTarget log_target_from_string(const char *s) _pure_;
void log_set_target(LogTarget target);
int log_set_target_from_string(const char *e);
LogTarget log_get_target(void) _pure_;
void log_settle_target(void);
void log_set_max_level(int level);
int log_set_max_level_from_string(const char *e);

View File

@ -1300,6 +1300,7 @@ int safe_fork_full(
/* Close the logs if requested, before we log anything. And make sure we reopen it if needed. */
log_close();
log_set_open_when_needed(true);
log_settle_target();
}
if (name) {

View File

@ -4201,6 +4201,7 @@ static int exec_child(
log_forget_fds();
log_set_open_when_needed(true);
log_settle_target();
/* In case anything used libc syslog(), close this here, too */
closelog();

View File

@ -3540,6 +3540,7 @@ static int inner_child(
* it again. Note that the other fds closed here are at least the locking and barrier fds. */
log_close();
log_set_open_when_needed(true);
log_settle_target();
(void) fdset_close_others(fds);

View File

@ -274,6 +274,7 @@ static void test_close_all_fds_inner(void) {
/* Close logging fd first, so that we don't confuse it by closing its fd */
log_close();
log_set_open_when_needed(true);
log_settle_target();
/* Close all but the ones to keep */
assert_se(close_all_fds(keep, n_keep) >= 0);