#949139 less: with option -R, the escape sequences should be sent in an atomic way so that they are not broken by stderr

Package:
less
Source:
less
Description:
pager program similar to more
Submitter:
Vincent Lefevre
Date:
2024-05-01 04:09:08 UTC
Severity:
normal
Tags:
#949139#5
Date:
2020-01-17 10:55:28 UTC
From:
To:
I've run the equivalent of ls with some options including --color
piped to less with the -R option, and after quitting less, the
xterm status sometimes get corrupt, apparently due to some margin
set up.

I've attached the xterm output log, but I can notice that an escape
sequence (sent to stdout) has been split by some error message (sent
to stderr):

  mcryptsetup^[[0m/^[ls: cannot open directory

where ^[ is the ESC character, and after the error messages, one has
"[m" corresponding to the end of the escape sequence.

The terminal should make sure that escape sequences from some FD are
not split by data coming from another FD.

This is not reproducible only with xterm, not with other terminals,
such as rxvt and gnome-terminal (but perhaps the race occurs
differently).

#949139#10
Date:
2020-01-17 11:01:57 UTC
From:
To:
terminals [...]".
#949139#15
Date:
2020-01-17 22:12:48 UTC
From:
To:
On Fri, Jan 17, 2020 at 12:01:57PM +0100, Vincent Lefevre wrote:
...

https://invisible-island.net/xterm/xterm.faq.html#vt100_wrapping

#949139#20
Date:
2020-01-17 22:12:48 UTC
From:
To:
On Fri, Jan 17, 2020 at 12:01:57PM +0100, Vincent Lefevre wrote:
...

https://invisible-island.net/xterm/xterm.faq.html#vt100_wrapping

#949139#25
Date:
2020-01-17 22:45:20 UTC
From:
To:
This is not this issue. The problem is that xterm sets up some margin,
and the lines at the top can no longer be erased. I need to use the
"reset" command to fix things.

#949139#30
Date:
2020-01-17 22:45:20 UTC
From:
To:
This is not this issue. The problem is that xterm sets up some margin,
and the lines at the top can no longer be erased. I need to use the
"reset" command to fix things.

#949139#33
Date:
2020-01-17 22:45:20 UTC
From:
To:
This is not this issue. The problem is that xterm sets up some margin,
and the lines at the top can no longer be erased. I need to use the
"reset" command to fix things.

#949139#38
Date:
2020-01-17 23:02:46 UTC
From:
To:
On my machine, the problem is almost always reproducible with

  ll -R /run | less

where

zira:~> where ll
ll: aliased to ls -l
zira:~> where ls
ls: aliased to \ls -bFv --color
/bin/ls

but it does not seem to be reproducible with

  /bin/ls -bFv --color -l -R /run | less

That's rather strange.

#949139#45
Date:
2020-01-17 23:26:34 UTC
From:
To:
The xterm logs show that stdout and stderr are mixed up in different
ways, which explains that the bug does not occur with the second
command. In short, there's some kind of race condition, and I suppose
that the difference is caused by a slightly different timing between
both commands. This *might* also explain why I cannot reproduce the
bug in other terminals.

#949139#50
Date:
2020-01-31 01:11:30 UTC
From:
To:
There's nothing for me to fix:

+ xterm's checking for invalid escape sequences, and stopping interpretation
  when it sees an error.  Some other terminal can check and handle the error
  differently (or in the examples you gave, simply not check at all).  Because
  xterm's using a state machine, it'll see errors that a switch/case logic
  won't address.

  In this report, you've assumed that terminals respond to errors identically.

+ there's no way that xterm can ever tell which bits came from your stdout
  and which from stderr.

  In this report you've assumed that it can.

+ for issues such as this, using "script" to generate a typescript file is
  the place to start (providing a reproducible test-case).

  You've described an error condition which you cannot reproduce at will.

You really ought to read the tag descriptions:

https://www.debian.org/Bugs/Developer#tags

#949139#53
Date:
2020-01-31 01:11:30 UTC
From:
To:
There's nothing for me to fix:

+ xterm's checking for invalid escape sequences, and stopping interpretation
  when it sees an error.  Some other terminal can check and handle the error
  differently (or in the examples you gave, simply not check at all).  Because
  xterm's using a state machine, it'll see errors that a switch/case logic
  won't address.

  In this report, you've assumed that terminals respond to errors identically.

+ there's no way that xterm can ever tell which bits came from your stdout
  and which from stderr.

  In this report you've assumed that it can.

+ for issues such as this, using "script" to generate a typescript file is
  the place to start (providing a reproducible test-case).

  You've described an error condition which you cannot reproduce at will.

You really ought to read the tag descriptions:

https://www.debian.org/Bugs/Developer#tags

#949139#58
Date:
2020-01-31 02:21:03 UTC
From:
To:
On Thu, Jan 30, 2020 at 08:11:30PM -0500, Thomas Dickey wrote:
...

The logfile doesn't give a clue about the screensize; there's no
cursor movement in it other than to the home-position.

Using unmap, which prints the escapes in visible form (and happens
to split the lines on escape characters), I see something a little
odd.  Here's a little slice from that listing:

\E]2;vinc17@zira - ~ | pts/23^G
\E(B
\E(B
\E[m
\E[?12l
\E[?25h
\E[?1007l\r
\E[0m
\E[27m
\E[24m
\E[J
\E[40m
\E[93mzira:~,2>

The odd part is the (xterm-specific)

	\E[?1007l\r

(the "\r" isn't part of the sequence, but that's how unmap presents it).

XTerm Control Sequences summarizes this:

            Ps = 1 0 0 7  -> Disable Alternate Scroll Mode, xterm.  This
          corresponds to the alternateScroll resource.

The manual page gives a little more information:

       alternateScroll (class ScrollCond)
               If “true”, the scroll-back and scroll-forw actions send
               cursor-up and -down keys when xterm is displaying the
               alternate screen.  The default is “false”.

               The alternateScroll state can also be set using a control
               sequence.

The changelog tells a little more:

                            Patch #291 - 2013/02/26

     * add  validity  check for xterm widget parameter to AlternateScroll
       function,  needed  to  handle  wheel mouse events in the scrollbar
       area    since    [451]patch    #282   changes   which   introduced
       alternateScroll feature (Redhat #874327).

Earlier in the output of unmap, it's switching to the alternate screen:

\E[?1049h

but then switches back out before the 1007's.  Just to check, I ran xterm
with that disabled, and it made no difference.

However, looking at the trace for something that might set the top/bottom
margins, I see a case (this time from Trace-parent.out):

parse 001B -> CASE_ESC ansi_table (used=0)
params 0 (0)
parse 006C -> CASE_HP_MEM_LOCK esc_table (used=0)
CASE_HP_MEM_LOCK
set_tb_margins 16..23, prior 0..23

That's documented in XTerm Control Sequences:

ESC l     Memory Lock (per HP terminals).  Locks memory above the cursor.

and it comes from (unmap) this section of the logfile:

\E[00;92mcryptsetup
\E[0m/
\Els: cannot open directory '/run/cups/certs': Permission denied\r
\nls: cannot open directory '/run/firejail/firejail.ro.dir': Permission denied\r
\n[m\r

xterm's doing what it's documented to do.

So... (see my previous message), there's no way for xterm (or any terminal)
to distinguish your shell's stdout from stderr.  There's only the usual
solution, which assumes that applications which spit out both will do
fflush's to keep the two in sync.

#949139#61
Date:
2020-01-31 02:21:03 UTC
From:
To:
On Thu, Jan 30, 2020 at 08:11:30PM -0500, Thomas Dickey wrote:
...

The logfile doesn't give a clue about the screensize; there's no
cursor movement in it other than to the home-position.

Using unmap, which prints the escapes in visible form (and happens
to split the lines on escape characters), I see something a little
odd.  Here's a little slice from that listing:

\E]2;vinc17@zira - ~ | pts/23^G
\E(B
\E(B
\E[m
\E[?12l
\E[?25h
\E[?1007l\r
\E[0m
\E[27m
\E[24m
\E[J
\E[40m
\E[93mzira:~,2>

The odd part is the (xterm-specific)

	\E[?1007l\r

(the "\r" isn't part of the sequence, but that's how unmap presents it).

XTerm Control Sequences summarizes this:

            Ps = 1 0 0 7  -> Disable Alternate Scroll Mode, xterm.  This
          corresponds to the alternateScroll resource.

The manual page gives a little more information:

       alternateScroll (class ScrollCond)
               If “true”, the scroll-back and scroll-forw actions send
               cursor-up and -down keys when xterm is displaying the
               alternate screen.  The default is “false”.

               The alternateScroll state can also be set using a control
               sequence.

The changelog tells a little more:

                            Patch #291 - 2013/02/26

     * add  validity  check for xterm widget parameter to AlternateScroll
       function,  needed  to  handle  wheel mouse events in the scrollbar
       area    since    [451]patch    #282   changes   which   introduced
       alternateScroll feature (Redhat #874327).

Earlier in the output of unmap, it's switching to the alternate screen:

\E[?1049h

but then switches back out before the 1007's.  Just to check, I ran xterm
with that disabled, and it made no difference.

However, looking at the trace for something that might set the top/bottom
margins, I see a case (this time from Trace-parent.out):

parse 001B -> CASE_ESC ansi_table (used=0)
params 0 (0)
parse 006C -> CASE_HP_MEM_LOCK esc_table (used=0)
CASE_HP_MEM_LOCK
set_tb_margins 16..23, prior 0..23

That's documented in XTerm Control Sequences:

ESC l     Memory Lock (per HP terminals).  Locks memory above the cursor.

and it comes from (unmap) this section of the logfile:

\E[00;92mcryptsetup
\E[0m/
\Els: cannot open directory '/run/cups/certs': Permission denied\r
\nls: cannot open directory '/run/firejail/firejail.ro.dir': Permission denied\r
\n[m\r

xterm's doing what it's documented to do.

So... (see my previous message), there's no way for xterm (or any terminal)
to distinguish your shell's stdout from stderr.  There's only the usual
solution, which assumes that applications which spit out both will do
fflush's to keep the two in sync.

#949139#68
Date:
2022-02-14 16:41:01 UTC
From:
To:
Control: reassign -1 less
Control: found -1 487-0.1
Control: found -1 590-1
Control: retitle -1 less: with option -R, the escape sequences should be sent in an atomic way so that they are not broken by stderr
Control: tags -1 upstream - wontfix

Indeed. Reassigning to less, which knows about the valid escape
sequences when option -R is used, so that it could ensure that
they are sent in an atomic way. The problem would still exist
with -r, but this option is already strongly discouraged.