File bsc#1220229-0001-Fix-tools-make-crm_mon-exit-upon-loss-of-the-attache.patch of Package pacemaker.38493
From 6f78cf724539bf8c4e957ba11c725b1c473c4288 Mon Sep 17 00:00:00 2001
From: "Gao,Yan" <ygao@suse.com>
Date: Mon, 22 Apr 2024 18:49:27 +0200
Subject: [PATCH] Fix: tools: make crm_mon exit upon loss of the attached
pseudo-terminal
Previously when crm_mon was running in console mode, if the attached
pseudo-terminal got lost, crm_mon would persist in the background and
raise the CPU usage to 100%.
The situation triggers if `use_pty` is enabled for `sudo`, in which case
it creates a separate pseudo-terminal device for its child process.
A producer:
- Enable `use_pty` by adding `Defaults use_pty` to /etc/sudoers
- Open a console and execute:
> sudo su -
# crm_mon
- Open another console, find the PID of crm_mon's bash parent and kill
it:
# kill -9 $(ps -C crm_mon -o ppid=)
The pty device created by `sudo` from the first console is basically
deleted, but crm_mon continues running in the background and raises the
CPU usage.
This commit fixes it by watching more conditions from stdin and exiting upon
(G_IO_ERR | G_IO_HUP).
The similar was reported and fixed for the `more` command:
https://github.com/util-linux/util-linux/pull/2635
https://github.com/util-linux/util-linux/pull/2795
The `tail` command is also impacted but hasn't been fixed so far.
There's the relevant discussion here:
https://github.com/sudo-project/sudo/issues/367
Fixes T16
---
tools/crm_mon.c | 35 +++++++++++++++++++++++++++++------
1 file changed, 29 insertions(+), 6 deletions(-)
Index: pacemaker-2.1.5+20221208.a3f44794f/tools/crm_mon.c
===================================================================
--- pacemaker-2.1.5+20221208.a3f44794f.orig/tools/crm_mon.c
+++ pacemaker-2.1.5+20221208.a3f44794f/tools/crm_mon.c
@@ -1045,6 +1045,28 @@ detect_user_input(GIOChannel *channel, G
{
int c;
gboolean config_mode = FALSE;
+ gboolean rc = G_SOURCE_CONTINUE;
+
+ /* If the attached pty device (pseudo-terminal) has been closed/deleted,
+ * the condition (G_IO_IN | G_IO_ERR | G_IO_HUP) occurs.
+ * Exit with an error, otherwise the process would persist in the
+ * background and significantly raise the CPU usage.
+ */
+ if ((condition & G_IO_ERR) && (condition & G_IO_HUP)) {
+ rc = G_SOURCE_REMOVE;
+ clean_up(CRM_EX_IOERR);
+ }
+
+ /* The connection/fd has been closed. Refresh the screen and remove this
+ * event source hence ignore stdin.
+ */
+ if (condition & (G_IO_HUP | G_IO_NVAL)) {
+ rc = G_SOURCE_REMOVE;
+ }
+
+ if ((condition & G_IO_IN) == 0) {
+ return rc;
+ }
while (1) {
@@ -1150,7 +1172,7 @@ detect_user_input(GIOChannel *channel, G
refresh:
refresh_after_event(FALSE, TRUE);
- return TRUE;
+ return rc;
}
#endif
@@ -1641,7 +1663,8 @@ main(int argc, char **argv)
ncurses_winch_handler = NULL;
io_channel = g_io_channel_unix_new(STDIN_FILENO);
- g_io_add_watch(io_channel, G_IO_IN, detect_user_input, NULL);
+ g_io_add_watch(io_channel, (G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL),
+ detect_user_input, NULL);
}
#endif
@@ -1653,10 +1676,6 @@ main(int argc, char **argv)
g_main_loop_run(mainloop);
g_main_loop_unref(mainloop);
- if (io_channel != NULL) {
- g_io_channel_shutdown(io_channel, TRUE, NULL);
- }
-
crm_info("Exiting %s", crm_system_name);
return clean_up(CRM_EX_OK);
@@ -2141,6 +2160,10 @@ clean_up(crm_exit_t exit_code)
/* Quitting crm_mon is much more complicated than it ought to be. */
/* (1) Close connections, free things, etc. */
+ if (io_channel != NULL) {
+ g_io_channel_shutdown(io_channel, TRUE, NULL);
+ }
+
cib__clean_up_connection(&cib);
clean_up_fencing_connection();
free(options.neg_location_prefix);