bug#24232: ls --color cannot be interrupted by a signal

2016-08-15 Thread Pádraig Brady
On 15/08/16 16:52, Kamil Dudka wrote:
> On Monday, August 15, 2016 15:55:13 Pádraig Brady wrote:
>> The signal catching functionality originated trying to restore terminal
>> color:
>> http://git.sv.gnu.org/gitweb/?p=coreutils.git;a=commitdiff;h=v4.5.3-89-g854
>> 9068
>>
>> That was adjusted to only outputting reset chars once for multiple signals,
>> http://git.sv.gnu.org/gitweb/?p=coreutils.git;a=commitdiff;h=v5.2.1-357-geae
>> 1b7f
>>
>> and not outputting reset chars at arbitrary places as that messes up
>> multi-byte chars:
>> http://git.sv.gnu.org/gitweb/?p=coreutils.git;a=commitdiff;h=v5.2.1-368-gad
>> c30a8
>>
>> Maybe we should just buffer internally at put_indicator
>> (_indicator[C_LEFT]); and output only at put_indicator
>> (_indicator[C_RIGHT]) or equivalent. That wouldn't introduce
>> significant overhead I think.
> 
> Internal buffering is certainly doable.  I guess there is some gnulib module 
> that already implements such a buffer?

Not that I noticed. The conditions for flushing tend to vary per app,
so we've slightly different variations in various utils, like lbuf_flush()
in factor(1), and buffer_or_output() in relpath(1).
We could take advantage of a PATH_MAX+A_BIT sized buffer to avoid realloc
complexities.

Actually we already buffer in quote_name(), so rather than outputting
the color sequences separately in print_name_with_quoting(), we could
pass those into quote_name() and it could write to its buffer,
and output the START+name+END atomically.

> However, what to do with signal handling then?  Drop the SA_RESTART flag and 
> implement EINTR loop only for the fwrite() call that writes data with escape 
> sequences to the terminal?

Hrm, the buffering above would avoid needing to explicitly output the color 
reset
sequence upon exit, but it would not avoid the need to fflush(), since stdio
might actually output the start and end color sequences in separate writes.
Drats, so if we had to manage signals anyway to do the fflush() the buffering
probably isn't worth it.

I'm not sure how to improve this.
Perhaps we should look at only enabling the signal handling before printing,
in the common case of outputting the sorted entries of a single directory.
In that way the open(), stat() etc. would be done with standard signal handling.






bug#24232: ls --color cannot be interrupted by a signal

2016-08-15 Thread Kamil Dudka
On Monday, August 15, 2016 15:55:13 Pádraig Brady wrote:
> The signal catching functionality originated trying to restore terminal
> color:
> http://git.sv.gnu.org/gitweb/?p=coreutils.git;a=commitdiff;h=v4.5.3-89-g854
> 9068
> 
> That was adjusted to only outputting reset chars once for multiple signals,
> http://git.sv.gnu.org/gitweb/?p=coreutils.git;a=commitdiff;h=v5.2.1-357-geae
> 1b7f
> 
> and not outputting reset chars at arbitrary places as that messes up
> multi-byte chars:
> http://git.sv.gnu.org/gitweb/?p=coreutils.git;a=commitdiff;h=v5.2.1-368-gad
> c30a8
> 
> Maybe we should just buffer internally at put_indicator
> (_indicator[C_LEFT]); and output only at put_indicator
> (_indicator[C_RIGHT]) or equivalent. That wouldn't introduce
> significant overhead I think.

Internal buffering is certainly doable.  I guess there is some gnulib module 
that already implements such a buffer?

However, what to do with signal handling then?  Drop the SA_RESTART flag and 
implement EINTR loop only for the fwrite() call that writes data with escape 
sequences to the terminal?

Kamil

> Pádraig





bug#24232: ls --color cannot be interrupted by a signal

2016-08-15 Thread Pádraig Brady
On 15/08/16 14:55, Kamil Dudka wrote:
> If 'ls --color' outputs to a terminal and a syscall blocks (e.g. while 
> reading 
> a directory from unresponsive network file system), it cannot be interrupted 
> by a signal.
> 
> This seems to be caused by the code of ls, which sets the SA_RESTART flag on 
> terminating signals.  A possible solution would be to reset the flag prior to 
> calling certain blocking syscalls and process the signals synchronously in an 
> EINTR loop.

Sounds expensive

> Alternatively, we can document this behavior as intended (or broken by 
> design) 
> and suggest users to disable color output or redirect the output off terminal 
> to work around the issue.
> 
> Any other idea how to solve it?
> 
> Originally reported at: https://bugzilla.redhat.com/1365933

The signal catching functionality originated trying to restore terminal color:
http://git.sv.gnu.org/gitweb/?p=coreutils.git;a=commitdiff;h=v4.5.3-89-g8549068

That was adjusted to only outputting reset chars once for multiple signals,
http://git.sv.gnu.org/gitweb/?p=coreutils.git;a=commitdiff;h=v5.2.1-357-geae1b7f

and not outputting reset chars at arbitrary places as that messes up multi-byte 
chars:
http://git.sv.gnu.org/gitweb/?p=coreutils.git;a=commitdiff;h=v5.2.1-368-gadc30a8

Maybe we should just buffer internally at put_indicator 
(_indicator[C_LEFT]);
and output only at put_indicator (_indicator[C_RIGHT]) or equivalent.
That wouldn't introduce significant overhead I think.

Pádraig






bug#24232: ls --color cannot be interrupted by a signal

2016-08-15 Thread Kamil Dudka
If 'ls --color' outputs to a terminal and a syscall blocks (e.g. while reading 
a directory from unresponsive network file system), it cannot be interrupted 
by a signal.

This seems to be caused by the code of ls, which sets the SA_RESTART flag on 
terminating signals.  A possible solution would be to reset the flag prior to 
calling certain blocking syscalls and process the signals synchronously in an 
EINTR loop.

Alternatively, we can document this behavior as intended (or broken by design) 
and suggest users to disable color output or redirect the output off terminal 
to work around the issue.

Any other idea how to solve it?

Originally reported at: https://bugzilla.redhat.com/1365933

Kamil