From: Jim Meyering Date: Thu, 8 Dec 2011 09:49:03 +0000 (+0100) Subject: ls: be responsive to interrupts when color-listing large directories X-Git-Tag: v8.15~38 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c592a00f8f8c7e6baeff575a3762459173153635;p=thirdparty%2Fcoreutils.git ls: be responsive to interrupts when color-listing large directories Starting with commit adc30a83, when using --color, ls inhibited interrupts to avoid corrupting the state of an output terminal. However, for very large directories, that inhibition rendered ls uninterruptible for too long, including a potentially long period even before any output is generated. * src/ls.c: Two phases of processing are time-consuming enough that they can provoke this: the readdir loop and the printing loop. The printing was supposed to be covered by a call to process_signals in (print_name_with_quoting): ... but that call was mistakenly guarded by a condition that might be false for many or even all files being processed. Call process_signals unconditionally. (print_dir): Also call process_signals in the readdir loop. * NEWS (Bug fixes): Mention it. Reported by Arkadiusz Miśkiewicz in http://bugs.gnu.org/10243 Co-authored-by: Eric Blake --- diff --git a/NEWS b/NEWS index de3888ddb4..0d4c83b67c 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,9 @@ GNU coreutils NEWS -*- outline -*- ** Bug fixes + ls --color many-entry-directory was uninterruptible for too long + [bug introduced in coreutils-5.2.1] + ls's -k option no longer affects how ls -l outputs file sizes. It now affects only the per-directory block counts written by -l, and the sizes written by -s. This is for compatibility with BSD diff --git a/THANKS.in b/THANKS.in index 5ecc29e630..afed5d4512 100644 --- a/THANKS.in +++ b/THANKS.in @@ -59,6 +59,7 @@ Anthony Thyssen anthony@griffith.edu.au Antonio Rendas ajrendas@yahoo.com Ariel Faigon ariel@cthulhu.engr.sgi.com Arjan Opmeer arjan.opmeer@gmail.com +Arkadiusz Miśkiewicz arekm@maven.pl Arne Henrik Juul arnej@imf.unit.no Arnold Robbins arnold@skeeve.com Arthur Pool pool@commerce.uq.edu.au diff --git a/src/ls.c b/src/ls.c index 8be9b6aed7..0d64bab159 100644 --- a/src/ls.c +++ b/src/ls.c @@ -2595,6 +2595,11 @@ print_dir (char const *name, char const *realname, bool command_line_arg) } else break; + + /* When processing a very large directory, and since we've inhibited + interrupts, this loop would take so long that ls would be annoyingly + uninterruptible. This ensures that it handles signals promptly. */ + process_signals (); } if (closedir (dirp) != 0) @@ -4060,9 +4065,9 @@ print_name_with_quoting (const struct fileinfo *f, if (stack) PUSH_CURRENT_DIRED_POS (stack); + process_signals (); if (used_color_this_time) { - process_signals (); prep_non_filename_text (); if (start_col / line_length != (start_col + width - 1) / line_length) put_indicator (&color_indicator[C_CLR_TO_EOL]);