Skip to content

Spurious newlines occur when a process forks #16

Closed
dsturnbull opened this Issue Sep 5, 2012 · 6 comments

2 participants

@dsturnbull

My dev setup is a big tmux pane on the left, then a grid of 2x2 on the right.
When I run a script in the left that shells out to run other things, the output on the other panes jumps up a line and repeats the last line once. Subsequent 'jumps' will not repeat, but eventually the whole output of those other panes will be blank, including the tmux pane separator ascii lines.

Confirmed this is reattach-to-user-namespace by disabling and rerunning the same script as before.

@ChrisJohnsen
Owner

The wrapper program should never be printing any blank lines by themselves; there are some blank lines in the middle of and at the end of the usage message, but it would probably be obvious if you were seeing the usage message.

The wrapper program also never does anything tmux specific (despite the name of the repository), so it seems quite unlikely that the wrapper could be causing this all on its own (since your wrapper-using script is being run in the left-pane and the panes on the right are the ones suffering from the “damage”).

The fact that the tmux pane separators are being mangled in some way indicates a bug in either tmux, your terminal program, or the terminfo database entry that tmux is using to lookup the escape sequences that will control your terminal program.

Could you provide some more details on your setup, and the script that uses the wrapper?

  • What terminal emulator(s) are you using above/around tmux?
    • a version of Terminal that comes with OS X? a version of iTerm 2?, a version of xterm?
  • How big is your initial window? How big are the panes in the 2x2 arrangement on the right-hand side?
    • Could you provide a series of commands that re-create this layout?
  • What does your wrapper-using script actually do?
    • Anything tmux related? Specifically something that you might be skipping as a part of disabling the wrapper-using portions of the script?

I have previously noticed some “unintended scrolling” in while using tmux select-layout, but never anything that damages the pane separators.

@dsturnbull

Thanks Chris.

I'm using Terminal with the TotalTerminal SIMBL plugin (http://totalterminal.binaryage.com). I checked this and it doesn't seem to be related.
I start at fullscreen, 1680x1050. Left pane is half the size, then the 2x2 grid is split evenly in the right hand side.

Command sequence would be:

  • tmux split-window -dh
  • tmux select-pane -R
  • tmux split-window -dh
  • tmux split-window -dv
  • tmux select-pane -R
  • tmux split-window -dv

I'm not sure my script uses the wrapper except perhaps incidentally as part of some kind of shell initialisation that uses tmux somehow? It's basically a python script that uses subprocess.Popen() to open things like 'tcpdump' and pipe things in/out. I also often get this corruption when viewing something in 'less'. So I think you're right about it being a bug in tmux/terminal/terminfo - except that I only get it when using reattach-to-user-namespace.

@ChrisJohnsen
Owner

I misinterpreted the last sentence in your first message as meaning that your script used the wrapper directly, but it sounds like that is not the case. Does your script include any tmux commands? It sounds like it may just be some sort of filter program that does not directly invoke the wrapper or tmux.

Are you just using the wrapper by setting default-command (as described in the README)? How are you disabling it?

Here is what I have tried to reproduce the problem:

  • OS X 10.8.1 Terminal
  • tmux 1.6 (via MacPorts)
    • started as /opt/local/bin/tmux -L test -f /tmp/tmc
      • -L test to isolate it from my normal server
      • /tmp/tmc has only one line: set-option -g default-command 'exec /path/to/reattach-to-user-namespace -l /opt/local/bin/zsh'
    • pane layout recreated with the commands you gave
  • less 418 (OS bundled /usr/bin/less)

Populate the right-side panes with the output of jot 100, jot 90, jot 80, and jot 70 to make any mangling visible.
Start /usr/bin/less /usr/share/dict/words in the left-hand pane. Furiously scroll up and down with Space, b, j, k, G, and g.

Nothing I did in the left pane seemed to perturb anything in the right-side panes.

Have you found a reliable way to reproduce the problem? If it is due to a particular sequence of output happening in the left-side pane, then you might be able to capture it with script command so that others could simply cat the output to reproduce the problem.

When you end up in a mis-drawn state, you might try typing your prefix key and then r. This sequence (in the default configuration) runs the command refresh-client, which makes tmux redraw the screen from scratch. It may help clear up any transient problems.

@dsturnbull

It hadn't happened for ages so I thought it was reattach-to-user-namespace since I disabled it a few weeks ago.
It just happened again this morning though. So we can safely rule out reattach-to-user-namespace. :)
I'll probably figure out whether this is now a zsh bug or tmux bug. Thanks!

@dsturnbull dsturnbull closed this Sep 24, 2012
@ChrisJohnsen
Owner

I have come across an “effect” that may be similar to (but not identical to) your original description. Just today I simplified it to a reproducible form, but

  • it did not need the wrapper,
  • I was not sure you were using zsh, and
  • I have never seen it damage tmux pane separators (even when it has happened enough to encompass the whole screen),

so I had not yet mentioned it.

Are you using a “fancy”, or multi-line prompt (PS1/PROMPT) in your zsh configuration?


After leaving a full-screen Terminal window open for several days (with your tmux pane configuration) I eventually noticed something that seemed similar to the problem you initially described. For reference here is what I have been using:

  • Terminal 2.3 (309), from OS X 10.8.2
  • tmux 1.6, from MacPorts
  • zsh 5.0.0, from MacPorts

Here is the zsh PROMPT configuration I was using:

setopt PROMPT_SUBST
PROMPT=$'%12K$(printf "%*s" $COLUMNS "")\r%(?..%1K%15F exited %? )%12K%0F%1(j.%2(j.[%j jobs].[%j job]) .)%2(L.[SHLVL %L] .)%1(l.\n.)%f%k%m:%4~ %n%# '

(Not that I recommend this kind of configuration. There is at least one buggy bit: writing in the last column (the printf that generates COLUMNS number of spaces), followed by a CR may not reliably stay on the same line across all terminal modes (some terminals might wrap to a new line). The only thing to recommend it is that it works even on terminals that do not support Background Color Erase (e.g. tmux).)

This simplified scenario reproduces “the effect” for me:

  1. Open a Terminal window.
  2. Run zsh, with the above PROMPT configuration.
  3. Run jot 1000 to fill the window with some output.
  4. Vertically resize the window (making it taller or shorter both work).

If the original terminal content looks something like this (the first and last line represent the bounds of the terminal, they are not part of the content—this example window is only five lines tall):

---- top of tty ----
998
999
1000
some PROMPT stuff
more PROMPT stuff% 
---- bottom of tty ----

Then, after resizing the Terminal window to make it one line shorter, zsh redraws its prompt in an erroneous way, resulting in this:

---- top of tty ----
999
some PROMPT stuff
more PROMPT stuff% 

---- bottom of tty ----

The original top line was lost due to the resizing, but zsh erased the 1000 line (along everything that was below it) and redrew its prompt one line too high. This kind of looks like a spurious newline, but it is different because we are actually losing a line “in the middle” of the screen (the 1000 line).

My guess is that zsh thinks the prompt is actually three lines high instead of only two lines. Looking at the log produced by a tmux started with the verbose flag (-v) shows that zsh issues the following control sequences when redrawing the prompt after the tty size change:

  1. CR CR: move to the first column on the current line (the second one is not needed, but does not hurt)
    The cursor is now in the first column of the more stuff line.
  2. ESC M ESC M: move up two lines (ESC M is “Reverse Index”: move up one line)
    The cursor is now in the first column of the 4 line.
  3. [some color changing sequences]
  4. ESC [ J: erase below cursor
    This erases the 4 line and both prompt lines.
  5. [the rest of the prompt]

While I have described this “effect” as it happens (for me) in a Terminal window, it also happens in tmux panes and windows. Further, I have found a bit of correlation between resuming from hibernation and Terminal windows causing spurious tty size change notifications (i.e. TIOCSWINSZ ioctl to SIGWINCH chains from Terminal to tmux to zsh), especially for (though not exclusive to) Terminal windows that are full-screen windows (in style offered on Lion and later). I had some luck inducing a higher percentage of hibernations after running pmset -g hibernatemode = 25 (always wake from disk instead of keeping memory powered during sleeps).

When the all of these combine (full-screen Terminal window running tmux with zsh at its prompt inside the panes, and resume from hibernation), I end up with something similar to your original description (i.e. without having to resort to the easier trigger of actually resizing the window): after a resume, some of the panes exhibit the pseudo-scrolling effect (the prompt moves up the screen, but lines are deleted from just above the prompt instead of pushing lines up and off the top of the screen).


Maybe zsh is being confused by something in your prompt?

Adding %{ and %} around the spaces-and-CR part of above-described PROMPT prevents “the effect” for me. zsh does not count (for positioning purposes) the characters between %{ and %}, so it ends up (correctly) thinking that the prompt is only two lines tall. It then only issues a single ESC M when redrawing the prompt.

Again, this does not address the pane separator damage, nor the repeated last line (unless that line is blank/empty), but it may be something to look into.

@dsturnbull

Wow, that's a seriously thorough investigation.

nice_orange=$'\e[38;5;208m'
nice_green=$'\e[38;5;154m'
nice_blue=$'\e[38;5;39m'
PROMPT="%{$nice_green%}%M%{$fg_reset%} %{$nice_blue%}%~%{$fg[default]%} %# "
RPS1='$(git_status) (%j)'

So my prompt is just one line high, but there is the RPS1 complicating things.
It's proving difficult to reproduce the problem.
I'll get rid of my RPS1 and see how it goes and report back after a while :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.