mirror of
https://github.com/systemd/systemd.git
synced 2024-12-02 14:53:35 +08:00
Merge pull request #33355 from YHNdnzj/shutdown-cad
shutdown: re-enable CAD handling in kernel at start, several other cleanups
This commit is contained in:
commit
9981bc210a
@ -24,37 +24,26 @@
|
||||
#include "utf8.h"
|
||||
|
||||
char* first_word(const char *s, const char *word) {
|
||||
size_t sl, wl;
|
||||
const char *p;
|
||||
|
||||
assert(s);
|
||||
assert(word);
|
||||
|
||||
/* Checks if the string starts with the specified word, either
|
||||
* followed by NUL or by whitespace. Returns a pointer to the
|
||||
* NUL or the first character after the whitespace. */
|
||||
/* Checks if the string starts with the specified word, either followed by NUL or by whitespace.
|
||||
* Returns a pointer to the NUL or the first character after the whitespace. */
|
||||
|
||||
sl = strlen(s);
|
||||
wl = strlen(word);
|
||||
|
||||
if (sl < wl)
|
||||
return NULL;
|
||||
|
||||
if (wl == 0)
|
||||
if (isempty(word))
|
||||
return (char*) s;
|
||||
|
||||
if (memcmp(s, word, wl) != 0)
|
||||
const char *p = startswith(s, word);
|
||||
if (!p)
|
||||
return NULL;
|
||||
|
||||
p = s + wl;
|
||||
if (*p == 0)
|
||||
if (*p == '\0')
|
||||
return (char*) p;
|
||||
|
||||
if (!strchr(WHITESPACE, *p))
|
||||
const char *nw = skip_leading_chars(p, WHITESPACE);
|
||||
if (p == nw)
|
||||
return NULL;
|
||||
|
||||
p += strspn(p, WHITESPACE);
|
||||
return (char*) p;
|
||||
return (char*) nw;
|
||||
}
|
||||
|
||||
char *strnappend(const char *s, const char *suffix, size_t b) {
|
||||
|
@ -2967,15 +2967,16 @@ static void manager_start_special(Manager *m, const char *name, JobMode mode) {
|
||||
}
|
||||
|
||||
static void manager_handle_ctrl_alt_del(Manager *m) {
|
||||
/* If the user presses C-A-D more than
|
||||
* 7 times within 2s, we reboot/shutdown immediately,
|
||||
* unless it was disabled in system.conf */
|
||||
assert(m);
|
||||
|
||||
/* If the user presses C-A-D more than 7 times within 2s, we reboot/shutdown immediately,
|
||||
* unless it was disabled in system.conf. */
|
||||
|
||||
if (ratelimit_below(&m->ctrl_alt_del_ratelimit) || m->cad_burst_action == EMERGENCY_ACTION_NONE)
|
||||
manager_start_special(m, SPECIAL_CTRL_ALT_DEL_TARGET, JOB_REPLACE_IRREVERSIBLY);
|
||||
else
|
||||
emergency_action(m, m->cad_burst_action, EMERGENCY_ACTION_WARN, NULL, -1,
|
||||
"Ctrl-Alt-Del was pressed more than 7 times within 2s");
|
||||
"Ctrl-Alt-Del was pressed more than 7 times within 2s");
|
||||
}
|
||||
|
||||
static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
|
||||
|
@ -188,7 +188,9 @@ static int switch_root_initramfs(void) {
|
||||
static int sync_making_progress(unsigned long long *prev_dirty) {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
unsigned long long val = 0;
|
||||
int ret;
|
||||
int r;
|
||||
|
||||
assert(prev_dirty);
|
||||
|
||||
f = fopen("/proc/meminfo", "re");
|
||||
if (!f)
|
||||
@ -196,13 +198,12 @@ static int sync_making_progress(unsigned long long *prev_dirty) {
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *line = NULL;
|
||||
unsigned long long ull = 0;
|
||||
int q;
|
||||
unsigned long long ull;
|
||||
|
||||
q = read_line(f, LONG_LINE_MAX, &line);
|
||||
if (q < 0)
|
||||
return log_warning_errno(q, "Failed to parse /proc/meminfo: %m");
|
||||
if (q == 0)
|
||||
r = read_line(f, LONG_LINE_MAX, &line);
|
||||
if (r < 0)
|
||||
return log_warning_errno(r, "Failed to parse /proc/meminfo: %m");
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
if (!first_word(line, "NFS_Unstable:") && !first_word(line, "Writeback:") && !first_word(line, "Dirty:"))
|
||||
@ -210,25 +211,20 @@ static int sync_making_progress(unsigned long long *prev_dirty) {
|
||||
|
||||
errno = 0;
|
||||
if (sscanf(line, "%*s %llu %*s", &ull) != 1) {
|
||||
if (errno != 0)
|
||||
log_warning_errno(errno, "Failed to parse /proc/meminfo: %m");
|
||||
else
|
||||
log_warning("Failed to parse /proc/meminfo");
|
||||
|
||||
log_warning_errno(errno_or_else(EIO), "Failed to parse /proc/meminfo field, ignoring: %m");
|
||||
return false;
|
||||
}
|
||||
|
||||
val += ull;
|
||||
}
|
||||
|
||||
ret = *prev_dirty > val;
|
||||
r = *prev_dirty > val;
|
||||
*prev_dirty = val;
|
||||
return ret;
|
||||
return r;
|
||||
}
|
||||
|
||||
static void sync_with_progress(void) {
|
||||
static int sync_with_progress(void) {
|
||||
unsigned long long dirty = ULLONG_MAX;
|
||||
unsigned checks;
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
||||
@ -238,37 +234,32 @@ static void sync_with_progress(void) {
|
||||
* the progress. If the timeout lapses, the assumption is that the particular sync stalled. */
|
||||
|
||||
r = asynchronous_sync(&pid);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to fork sync(): %m");
|
||||
return;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to fork sync(): %m");
|
||||
|
||||
log_info("Syncing filesystems and block devices.");
|
||||
|
||||
/* Start monitoring the sync operation. If more than
|
||||
* SYNC_PROGRESS_ATTEMPTS lapse without progress being made,
|
||||
* we assume that the sync is stalled */
|
||||
for (checks = 0; checks < SYNC_PROGRESS_ATTEMPTS; checks++) {
|
||||
for (unsigned checks = 0; checks < SYNC_PROGRESS_ATTEMPTS; checks++) {
|
||||
r = wait_for_terminate_with_timeout(pid, SYNC_TIMEOUT_USEC);
|
||||
if (r == 0)
|
||||
/* Sync finished without error.
|
||||
* (The sync itself does not return an error code) */
|
||||
return;
|
||||
else if (r == -ETIMEDOUT) {
|
||||
/* Reset the check counter if the "Dirty" value is
|
||||
* decreasing */
|
||||
if (sync_making_progress(&dirty) > 0)
|
||||
checks = 0;
|
||||
} else {
|
||||
log_error_errno(r, "Failed to sync filesystems and block devices: %m");
|
||||
return;
|
||||
}
|
||||
/* Sync finished without error (sync() call itself does not return an error code) */
|
||||
return 0;
|
||||
if (r != -ETIMEDOUT)
|
||||
return log_error_errno(r, "Failed to sync filesystems and block devices: %m");
|
||||
|
||||
/* Reset the check counter if we made some progress */
|
||||
if (sync_making_progress(&dirty) > 0)
|
||||
checks = 0;
|
||||
}
|
||||
|
||||
/* Only reached in the event of a timeout. We should issue a kill
|
||||
* to the stray process. */
|
||||
log_error("Syncing filesystems and block devices - timed out, issuing SIGKILL to PID "PID_FMT".", pid);
|
||||
/* Only reached in the event of a timeout. We should issue a kill to the stray process. */
|
||||
(void) kill(pid, SIGKILL);
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ETIMEDOUT),
|
||||
"Syncing filesystems and block devices - timed out, issuing SIGKILL to PID "PID_FMT".",
|
||||
pid);
|
||||
}
|
||||
|
||||
static int read_current_sysctl_printk_log_level(void) {
|
||||
@ -383,6 +374,11 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
log_set_always_reopen_console(true);
|
||||
|
||||
/* Re-enable reboot on Ctrl-Alt-Delete, so that if close/broadcast_signal/umount/... stalls,
|
||||
* or an error is encountered and we freeze(), the user can still initiate a force reboot
|
||||
* through kernel. */
|
||||
(void) reboot(RB_ENABLE_CAD);
|
||||
|
||||
r = parse_argv(argc, argv);
|
||||
if (r < 0)
|
||||
goto error;
|
||||
@ -436,7 +432,7 @@ int main(int argc, char *argv[]) {
|
||||
* desperately trying to sync IO to disk within their timeout. Do not remove this sync, data corruption will
|
||||
* result. */
|
||||
if (!in_container)
|
||||
sync_with_progress();
|
||||
(void) sync_with_progress();
|
||||
|
||||
disable_coredumps();
|
||||
disable_binfmt();
|
||||
@ -604,7 +600,7 @@ int main(int argc, char *argv[]) {
|
||||
* which might have caused IO, hence let's do it once more. Do not remove this sync, data corruption
|
||||
* will result. */
|
||||
if (!in_container)
|
||||
sync_with_progress();
|
||||
(void) sync_with_progress();
|
||||
|
||||
notify_supervisor();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user