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);
openSUSE Build Service is sponsored by