Resolves: #1365933 - ls: allow interruption when reading slow directories

This commit is contained in:
Kamil Dudka 2016-09-07 20:17:56 +02:00
parent 0e3a55d8dc
commit 380647993e
2 changed files with 243 additions and 1 deletions

View File

@ -0,0 +1,236 @@
From 9338b244572e07bbff314b3570228e8cf43f1300 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Tue, 6 Sep 2016 17:38:26 +0200
Subject: [PATCH] ls: allow interruption when reading slow directories
Postpone installation of signal handlers until they're needed.
That is right before the first escape sequence is printed.
* src/ls.c (signal_setup): A new function refactored from main()
to set and restore signal handlers.
(main): Move signal handler setup to put_indicator()
so that the default signal handling is untouched as long as possible.
Adjusted condition for restoring signal handlers to reflect the change.
(put_indicator): Install signal handlers if called for the very first
time. It uses the same code that was in main() prior to this commit.
* NEWS: Mention the improvement.
See https://bugzilla.redhat.com/1365933
Fixes http://bugs.gnu.org/24232
Upstream-commit: 5445f7811ff945ea13aa2a0fd797eb4c0a0e4db0
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
src/ls.c | 161 ++++++++++++++++++++++++++++++++++++---------------------------
1 file changed, 93 insertions(+), 68 deletions(-)
diff --git a/src/ls.c b/src/ls.c
index d976036..66df307 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -1244,13 +1244,12 @@ process_signals (void)
}
}
-int
-main (int argc, char **argv)
-{
- int i;
- struct pending *thispend;
- int n_files;
+/* Setup signal handlers if INIT is true,
+ otherwise restore to the default. */
+static void
+signal_setup (bool init)
+{
/* The signals that are trapped, and the number of such signals. */
static int const sig[] =
{
@@ -1278,8 +1277,77 @@ main (int argc, char **argv)
enum { nsigs = ARRAY_CARDINALITY (sig) };
#if ! SA_NOCLDSTOP
- bool caught_sig[nsigs];
+ static bool caught_sig[nsigs];
+#endif
+
+ int j;
+
+ if (init)
+ {
+#if SA_NOCLDSTOP
+ struct sigaction act;
+
+ sigemptyset (&caught_signals);
+ for (j = 0; j < nsigs; j++)
+ {
+ sigaction (sig[j], NULL, &act);
+ if (act.sa_handler != SIG_IGN)
+ sigaddset (&caught_signals, sig[j]);
+ }
+
+ act.sa_mask = caught_signals;
+ act.sa_flags = SA_RESTART;
+
+ for (j = 0; j < nsigs; j++)
+ if (sigismember (&caught_signals, sig[j]))
+ {
+ act.sa_handler = sig[j] == SIGTSTP ? stophandler : sighandler;
+ sigaction (sig[j], &act, NULL);
+ }
+#else
+ for (j = 0; j < nsigs; j++)
+ {
+ caught_sig[j] = (signal (sig[j], SIG_IGN) != SIG_IGN);
+ if (caught_sig[j])
+ {
+ signal (sig[j], sig[j] == SIGTSTP ? stophandler : sighandler);
+ siginterrupt (sig[j], 0);
+ }
+ }
#endif
+ }
+ else /* restore. */
+ {
+#if SA_NOCLDSTOP
+ for (j = 0; j < nsigs; j++)
+ if (sigismember (&caught_signals, sig[j]))
+ signal (sig[j], SIG_DFL);
+#else
+ for (j = 0; j < nsigs; j++)
+ if (caught_sig[j])
+ signal (sig[j], SIG_DFL);
+#endif
+ }
+}
+
+static inline void
+signal_init (void)
+{
+ signal_setup (true);
+}
+
+static inline void
+signal_restore (void)
+{
+ signal_setup (false);
+}
+
+int
+main (int argc, char **argv)
+{
+ int i;
+ struct pending *thispend;
+ int n_files;
initialize_main (&argc, &argv);
set_program_name (argv[0]);
@@ -1314,46 +1382,6 @@ main (int argc, char **argv)
|| (is_colored (C_EXEC) && color_symlink_as_referent)
|| (is_colored (C_MISSING) && format == long_format))
check_symlink_color = true;
-
- /* If the standard output is a controlling terminal, watch out
- for signals, so that the colors can be restored to the
- default state if "ls" is suspended or interrupted. */
-
- if (0 <= tcgetpgrp (STDOUT_FILENO))
- {
- int j;
-#if SA_NOCLDSTOP
- struct sigaction act;
-
- sigemptyset (&caught_signals);
- for (j = 0; j < nsigs; j++)
- {
- sigaction (sig[j], NULL, &act);
- if (act.sa_handler != SIG_IGN)
- sigaddset (&caught_signals, sig[j]);
- }
-
- act.sa_mask = caught_signals;
- act.sa_flags = SA_RESTART;
-
- for (j = 0; j < nsigs; j++)
- if (sigismember (&caught_signals, sig[j]))
- {
- act.sa_handler = sig[j] == SIGTSTP ? stophandler : sighandler;
- sigaction (sig[j], &act, NULL);
- }
-#else
- for (j = 0; j < nsigs; j++)
- {
- caught_sig[j] = (signal (sig[j], SIG_IGN) != SIG_IGN);
- if (caught_sig[j])
- {
- signal (sig[j], sig[j] == SIGTSTP ? stophandler : sighandler);
- siginterrupt (sig[j], 0);
- }
- }
-#endif
- }
}
if (dereference == DEREF_UNDEFINED)
@@ -1466,32 +1494,21 @@ main (int argc, char **argv)
print_dir_name = true;
}
- if (print_with_color)
+ if (print_with_color && used_color)
{
int j;
- if (used_color)
- {
- /* Skip the restore when it would be a no-op, i.e.,
- when left is "\033[" and right is "m". */
- if (!(color_indicator[C_LEFT].len == 2
- && memcmp (color_indicator[C_LEFT].string, "\033[", 2) == 0
- && color_indicator[C_RIGHT].len == 1
- && color_indicator[C_RIGHT].string[0] == 'm'))
- restore_default_color ();
- }
+ /* Skip the restore when it would be a no-op, i.e.,
+ when left is "\033[" and right is "m". */
+ if (!(color_indicator[C_LEFT].len == 2
+ && memcmp (color_indicator[C_LEFT].string, "\033[", 2) == 0
+ && color_indicator[C_RIGHT].len == 1
+ && color_indicator[C_RIGHT].string[0] == 'm'))
+ restore_default_color ();
+
fflush (stdout);
- /* Restore the default signal handling. */
-#if SA_NOCLDSTOP
- for (j = 0; j < nsigs; j++)
- if (sigismember (&caught_signals, sig[j]))
- signal (sig[j], SIG_DFL);
-#else
- for (j = 0; j < nsigs; j++)
- if (caught_sig[j])
- signal (sig[j], SIG_DFL);
-#endif
+ signal_restore ();
/* Act on any signals that arrived before the default was restored.
This can process signals out of order, but there doesn't seem to
@@ -4482,6 +4499,14 @@ put_indicator (const struct bin_str *ind)
if (! used_color)
{
used_color = true;
+
+ /* If the standard output is a controlling terminal, watch out
+ for signals, so that the colors can be restored to the
+ default state if "ls" is suspended or interrupted. */
+
+ if (0 <= tcgetpgrp (STDOUT_FILENO))
+ signal_init ();
+
prep_non_filename_text ();
}
--
2.7.4

View File

@ -1,7 +1,7 @@
Summary: A set of basic GNU tools commonly used in shell scripts
Name: coreutils
Version: 8.25
Release: 14%{?dist}
Release: 15%{?dist}
License: GPLv3+
Group: System Environment/Base
Url: http://www.gnu.org/software/coreutils/
@ -21,6 +21,8 @@ Source10: coreutils-find-requires.sh
Patch952: coreutils-8.25-intall-Z-selinux.patch
# fix 'sort -h -k' in locales that use blank as thousands separator (#1355780)
Patch953: coreutils-8.25-sort-thousands-sep.patch
# ls: allow interruption when reading slow directories (#1365933)
Patch954: coreutils-8.25-ls-signal.patch
# Our patches
#general patch to workaround koji build system issues
@ -213,6 +215,7 @@ tee DIR_COLORS{,.256color,.lightbgcolor} <src/dircolors.hin >/dev/null
# upstream patches
%patch953 -p1
%patch954 -p1
chmod a+x \
tests/df/direct.sh \
@ -342,6 +345,9 @@ fi
%license COPYING
%changelog
* Wed Sep 07 2016 Kamil Dudka <kdudka@redhat.com> - 8.25-15
- ls: allow interruption when reading slow directories (#1365933)
* Tue Jul 19 2016 Kamil Dudka <kdudka@redhat.com> - 8.25-14
- run autoreconf in %%prep
- drop post-install fix for Japanese locales that no longer applies