Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unexpected output from redirection

I'm encountering a strange problem when redirecting STDOUT and STDERR. The following works as expected:

$ gvim --version > /tmp/version.out
$ ls -l /tmp/version.out
-rw-r--r--. 1 blah blah 3419 Jun 27 17:28 /tmp/version.out

There are 3419 characters in the output file and when I look at the file, it contains what I expect.

However, it does not work as expected when I do the following:

$ gvim --version > /tmp/version.out 2> /tmp/version.err
$ ls -latr /tmp/version.*
-rw-r--r--. 1 blah blah 0 Jun 27 17:29 /tmp/version.out
-rw-r--r--. 1 blah blah 0 Jun 27 17:29 /tmp/version.err

Notice that both the .out and the .err files are zero length this time. I tried this with an ls command and it works as expected:

$ ls . /ZZZ > /tmp/ls.out 2> /tmp/ls.err
$ ls -l /tmp/ls.*
-rw-r--r--. 1 blah blah 50 Jun 27 17:45 /tmp/ls.err
-rw-r--r--. 1 blah blah 33 Jun 27 17:45 /tmp/ls.out

Here, the STDERR gets redirected properly:

$ cat /tmp/ls.err
ls: cannot access /ZZZ: No such file or directory

I did an strace on gvim --version and confirmed that it's trying to write the version info to STDOUT (fd 1). It shouldn't matter either way though since I'm trying to capture both STDOUT and STDERR.

What's going on here?

like image 922
MacGruber Avatar asked Jun 28 '17 00:06

MacGruber


2 Answers

Congratulations, you just found a bug in gvim! Correct procedure is to file a new issue on GitHub.

You should first try another variations of the bug, so that developers have the debugging easier.

For example, redirecting only STDERR also causes the error, because there was no output written. Also there was returned success (0), which is obviously an bug.

$ gvim --version 2> /tmp/version.err
$ echo $?
0

By only looking into the code one may search for the bug somewhere in version printing, or anywhere in generic --version argument processing, not being done by gtk.

To answer your question

What is going on?

It's a program error, made by developers of gvim and I would not recommend you to put effort into finding its root cause unless you are experienced with coding vim or if you want to learn, how vim works. In that case, your best shot is to fork the repo and after fixing it, submitting a pull request, so that everyone can benefit from your work.

like image 89
jirislav Avatar answered Nov 02 '22 21:11

jirislav


The specific condition that triggers the bug seems to be when standard error is not a terminal. When I tried redirecting standard error to another terminal device, the --version message was still printed to standard output.

ek@Io:~$ gvim --version 2>/dev/null
ek@Io:~$ tty
/dev/pts/1
ek@Io:~$ who
ek       tty7         2017-07-05 02:48 (:0)
ek       pts/1        2017-07-10 09:10 (192.168.10.3)
ek       pts/3        2017-07-10 09:23 (192.168.10.3)
ek@Io:~$ gvim --version 2>/dev/pts/3
VIM - Vi IMproved 7.4 (2013 Aug 10, compiled Nov 24 2016 16:44:48)
....

Apparently Vim calls isatty(2) to help figure out if it should use a terminal at all. From a comment in gui.c:

Return TRUE if still starting up and there is no place to enter text. For GTK and X11 we check if stderr is not a tty, which means we were (probably) started from the desktop. Also check stdin, "vim >& file" does allow typing on stdin.

But the rest of that comment (i.e., the part I didn't highlight), and instances of isatty(2) throughout multiple files, make it not immediately obvious what ought to be changed.

Running grep -RF 'isatty(2)' on the source tree revealed that this is used in gui.c, message.c, and main.c. (That doesn't mean the bug is in all those files, of course.) You might also look at all the instances of isatty in the source code.

In any case, as jirislav says, this ought to be reported as a bug--even if a full explanation of the problem is not yet apparent. I am able to reproduce this with the current upstream sources (commit 163095f).

like image 25
Eliah Kagan Avatar answered Nov 02 '22 22:11

Eliah Kagan