]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lib/pager: Use original stderr in pager_close
authorTobias Stoeckmann <tobias@stoeckmann.org>
Wed, 4 Feb 2026 19:46:57 +0000 (20:46 +0100)
committerTobias Stoeckmann <tobias@stoeckmann.org>
Wed, 4 Feb 2026 20:46:39 +0000 (21:46 +0100)
Having restored stdout/stderr before calling wait_for_pager allows
potential error messages to be printed on terminal instead of being lost
due to an already closed pipe stderr.

Although dup2 closes the target descriptor, make sure that the pipe
is closed even if dup2 fails.

With everything in place, call exit after restoring the original signal
handlers. This way, signals received between wait_for_pager and signal
restoration are processed as well. A race condition exists if multiple
signals are received, which would allow original handlers to be
processed before exit is called, yet the overhead of properly blocking
signals and unblocking them is most likely not worth the effort.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
lib/pager.c

index 3cb96dcc3a8d93558f1ae22d5d1a36a08a23d7f0..a87a2b656332261c63c3ca267e187e07be446219 100644 (file)
@@ -105,10 +105,6 @@ static void wait_for_pager(void)
        if (!pager_process.pid)
                return;
 
-       /* signal EOF to pager */
-       close(STDOUT_FILENO);
-       close(STDERR_FILENO);
-
        do {
                waiting = waitpid(pager_process.pid, NULL, 0);
                if (waiting == -1 && errno != EINTR)
@@ -124,6 +120,11 @@ static void catch_signal(int signo)
 static void wait_for_pager_signal(int signo __attribute__ ((__unused__)))
 {
        UL_PROTECT_ERRNO;
+
+       /* signal EOF to pager */
+       close(STDOUT_FILENO);
+       close(STDERR_FILENO);
+
        wait_for_pager();
        _exit(EXIT_FAILURE);
 }
@@ -268,10 +269,9 @@ void pager_close(void)
 
        fflush(NULL);
 
-       wait_for_pager();
-
-       if (caught_signal)
-               _exit(EXIT_FAILURE);
+       /* signal EOF to pager */
+       close(STDOUT_FILENO);
+       close(STDERR_FILENO);
 
        /* restore original output */
        clearerr(stdout);
@@ -282,6 +282,8 @@ void pager_close(void)
        close(pager_process.org_out);
        close(pager_process.org_err);
 
+       wait_for_pager();
+
        /* restore original signal settings */
        sigaction(SIGCHLD, &pager_process.orig_sigchld, NULL);
        sigaction(SIGINT,  &pager_process.orig_sigint, NULL);
@@ -290,6 +292,9 @@ void pager_close(void)
        sigaction(SIGQUIT, &pager_process.orig_sigquit, NULL);
        sigaction(SIGPIPE, &pager_process.orig_sigpipe, NULL);
 
+       if (caught_signal)
+               exit(EXIT_FAILURE);
+
        memset(&pager_process, 0, sizeof(pager_process));
        caught_signal = 0;
 }