Merge pull request #13367 from poettering/null-console-fixes

Fixes inspired by console=null
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2019-08-20 21:13:36 +02:00 committed by GitHub
commit ba90388221
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 51 additions and 45 deletions

View file

@ -87,11 +87,13 @@ static int log_open_console(void) {
}
if (console_fd < 3) {
console_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
if (console_fd < 0)
return console_fd;
int fd;
console_fd = fd_move_above_stdio(console_fd);
fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
if (fd < 0)
return fd;
console_fd = fd_move_above_stdio(fd);
}
return 0;
@ -372,13 +374,11 @@ static int write_to_console(
if (errno == EIO && getpid_cached() == 1) {
/* If somebody tried to kick us from our
* console tty (via vhangup() or suchlike),
* try to reconnect */
/* If somebody tried to kick us from our console tty (via vhangup() or suchlike), try
* to reconnect. */
log_close_console();
log_open_console();
(void) log_open_console();
if (console_fd < 0)
return 0;
@ -586,7 +586,7 @@ int log_dispatch_internal(
level |= log_facility;
if (open_when_needed)
log_open();
(void) log_open();
do {
char *e;
@ -629,7 +629,7 @@ int log_dispatch_internal(
k = write_to_kmsg(level, error, file, line, func, buffer);
if (k < 0) {
log_close_kmsg();
log_open_console();
(void) log_open_console();
}
}
@ -795,7 +795,7 @@ _noreturn_ void log_assert_failed_realm(
const char *file,
int line,
const char *func) {
log_open();
(void) log_open();
log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_CRIT), text, file, line, func,
"Assertion '%s' failed at %s:%u, function %s(). Aborting.");
abort();
@ -807,7 +807,7 @@ _noreturn_ void log_assert_failed_unreachable_realm(
const char *file,
int line,
const char *func) {
log_open();
(void) log_open();
log_assert(LOG_REALM_PLUS_LEVEL(realm, LOG_CRIT), text, file, line, func,
"Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
abort();
@ -1356,5 +1356,5 @@ void log_setup_service(void) {
log_set_target(LOG_TARGET_AUTO);
log_parse_environment();
log_open();
(void) log_open();
}

View file

@ -578,22 +578,29 @@ int vt_disallocate(const char *name) {
int make_console_stdio(void) {
int fd, r;
/* Make /dev/console the controlling terminal and stdin/stdout/stderr */
/* Make /dev/console the controlling terminal and stdin/stdout/stderr, if we can. If we can't use
* /dev/null instead. This is particularly useful if /dev/console is turned off, e.g. if console=null
* is specified on the kernel command line. */
fd = acquire_terminal("/dev/console", ACQUIRE_TERMINAL_FORCE|ACQUIRE_TERMINAL_PERMISSIVE, USEC_INFINITY);
if (fd < 0)
return log_error_errno(fd, "Failed to acquire terminal: %m");
if (fd < 0) {
log_warning_errno(fd, "Failed to acquire terminal, using /dev/null stdin/stdout/stderr instead: %m");
r = reset_terminal_fd(fd, true);
if (r < 0)
log_warning_errno(r, "Failed to reset terminal, ignoring: %m");
r = make_null_stdio();
if (r < 0)
return log_error_errno(r, "Failed to make /dev/null stdin/stdout/stderr: %m");
r = rearrange_stdio(fd, fd, fd); /* This invalidates 'fd' both on success and on failure. */
if (r < 0)
return log_error_errno(r, "Failed to make terminal stdin/stdout/stderr: %m");
} else {
r = reset_terminal_fd(fd, true);
if (r < 0)
log_warning_errno(r, "Failed to reset terminal, ignoring: %m");
r = rearrange_stdio(fd, fd, fd); /* This invalidates 'fd' both on success and on failure. */
if (r < 0)
return log_error_errno(r, "Failed to make terminal stdin/stdout/stderr: %m");
}
reset_terminal_feature_caches();
return 0;
}

View file

@ -98,14 +98,12 @@ int parse_confirm_spawn(const char *value, char **console) {
if (r == 0) {
*console = NULL;
return 0;
}
if (r > 0) /* on with default tty */
} else if (r > 0) /* on with default tty */
s = strdup("/dev/console");
else if (is_path(value)) /* on with fully qualified path */
s = strdup(value);
else /* on with only a tty file name, not a fully qualified path */
s = strjoin("/dev/", value);
s = path_join("/dev/", value);
if (!s)
return -ENOMEM;

View file

@ -4072,10 +4072,11 @@ static bool manager_get_show_status(Manager *m, StatusType type) {
const char *manager_get_confirm_spawn(Manager *m) {
static int last_errno = 0;
const char *vc = m->confirm_spawn;
struct stat st;
int r;
assert(m);
/* Here's the deal: we want to test the validity of the console but don't want
* PID1 to go through the whole console process which might block. But we also
* want to warn the user only once if something is wrong with the console so we
@ -4091,25 +4092,26 @@ const char *manager_get_confirm_spawn(Manager *m) {
* reason the configured console is not ready, we fallback to the default
* console. */
if (!vc || path_equal(vc, "/dev/console"))
return vc;
if (!m->confirm_spawn || path_equal(m->confirm_spawn, "/dev/console"))
return m->confirm_spawn;
r = stat(vc, &st);
if (r < 0)
if (stat(m->confirm_spawn, &st) < 0) {
r = -errno;
goto fail;
}
if (!S_ISCHR(st.st_mode)) {
errno = ENOTTY;
r = -ENOTTY;
goto fail;
}
last_errno = 0;
return vc;
return m->confirm_spawn;
fail:
if (last_errno != errno) {
last_errno = errno;
log_warning_errno(errno, "Failed to open %s: %m, using default console", vc);
}
if (last_errno != r)
last_errno = log_warning_errno(r, "Failed to open %s, using default console: %m", m->confirm_spawn);
return "/dev/console";
}

View file

@ -169,12 +169,12 @@ static int process_progress(int fd) {
f = fdopen(fd, "r");
if (!f) {
safe_close(fd);
return -errno;
return log_debug_errno(errno, "Failed to use pipe: %m");
}
console = fopen("/dev/console", "we");
if (!console)
return -ENOMEM;
return log_debug_errno(errno, "Failed to open /dev/console, can't print progress output: %m");
for (;;) {
int pass, m;
@ -189,10 +189,9 @@ static int process_progress(int fd) {
r = log_warning_errno(errno, "Failed to read from progress pipe: %m");
else if (feof(f))
r = 0;
else {
log_warning("Failed to parse progress pipe data");
r = -EBADMSG;
}
else
r = log_warning_errno(SYNTHETIC_ERRNO(errno), "Failed to parse progress pipe data");
break;
}