Re: Strange pager (less, more) behavior



On Wed, 29 Mar 2006 07:28:12 +0200,
Kasper Dupont <97619472400731189722@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
wrote:
Dave Ulrick wrote:

FILE *f;
char *filename;

if (!filename || strcmp (filename, "-") == 0)
f = stdout;
else
f = fopen (filename, "w");

In such a manner, my programs frequently assign stdout and stderr
to program-defined FILE pointers, but I _never_ assign values to
stdout or stderr, and I never use freopen. As far as I've been able
to tell from C programming books and the Internet, my use of
stdout and stderr is legitimate.

That is a perfectly valid way to use stdout. But then you'd
have to look on filename again to figure out if you need to
call fclose. Or you could just compare the pointers:
if (f != stdout) fclose(f);

That's the approach I'm using right now in my fclose() wrapper function:

int closefile (FILE *f)
{
if (f == stdin || f == stdout || f == stderr)
return 0;
else
return fclose (f);
}

This sounds a bit strange. When you say it happens with
grep do you mean something like
./myprogram 2>&1 | grep foobar | less
or is it a command line not even involving your own program?

The latter. I don't recall the exact program, but it was something like:

$ some-program-I-didnt-write args | less

Although it may be significant that I've seen this problem only with
Linux 2.6.9 and above, I'm open to the possibility that my programs
might somehow be abusing stdout and stderr, thus helping to cause this
strange problem.

I don't think above piece of code is the reason for the
problem, but maybe you are doing something else wrong.
Could you post the source for the smallest program which
produce the problem?

I'll see if I can work something up along the lines of a 'cat' clone.

The C programming resources I've seen don't provide
much of an example of how to direct file streams to stdout or stderr,
but if you could provide me with a pointer to a book or Web document
that provides details on how programs should handle stdout/stderr, that
would be great. Also, I've seen different opinions on if/when the stdio
streams ought to be fclose()d. I lean towards not explicitly closing
them, but I've seen this problem occur whether I fclose() them or not.

I'd avoid fclose on stdin, stdout, and stderr. And of
course that applies also to situations like this:
FILE *f=stdout;
...
fclose(f);
which is really no different from fclose(stdout);

True.

To fix the problem you first need to find the cause, which
means it is important to find a way to reproduce it. Maybe if
you called it in a loop, it would happen once in a while.
while true
do
./myprogram 2>&1 | less
done
the problem is to figure out how to quit less automatically in
all those cases where it works as intended.

I'll see if I can think of a way to do that.

Another thing to test is whether you can change the timing
slightly to provoke the problem. What happens if you do this?
( sleep 1 ; ./myprogram 2>&1 ) | less
./myprogram 2>&1 | ( sleep 1 ; less )

I'll give that a try. In the meantime, I'll mention that I've been
unable to recreate the problem while running either my program or
'less' via 'strace'. Since 'strace' no doubt slows the program's
execution, this may lend credence to the possibility that this is one of
those pesky "timing" errors.

Dave
--
Dave Ulrick
Email: d-ulrick@xxxxxxx
Web: http://www.niu.edu/~ulrick/
.



Relevant Pages

  • FAQ 8.25 How can I capture STDERR from an external command?
    ... This message is one of several periodic postings to comp.lang.perl.misc ... both STDOUT and STDERR will go the same place as the ... script's STDOUT and STDERR, unless the systemcommand redirects them. ... You can also use file-descriptor redirection to make STDERR a duplicate ...
    (comp.lang.perl.misc)
  • FAQ 8.25 How can I capture STDERR from an external command?
    ... This message is one of several periodic postings to comp.lang.perl.misc ... both STDOUT and STDERR will go the same place as the ... script's STDOUT and STDERR, unless the systemcommand redirects them. ... You can also use file-descriptor redirection to make STDERR a duplicate ...
    (comp.lang.perl.misc)
  • FAQ 8.25 How can I capture STDERR from an external command?
    ... This message is one of several periodic postings to comp.lang.perl.misc ... both STDOUT and STDERR will go the same place as the ... script's STDOUT and STDERR, unless the systemcommand redirects them. ... You can also use file-descriptor redirection to make STDERR a duplicate ...
    (comp.lang.perl.misc)
  • FAQ 8.25 How can I capture STDERR from an external command?
    ... both STDOUT and STDERR will go the same place as the ... script's STDOUT and STDERR, unless the systemcommand redirects them. ... You can also use file-descriptor redirection to make STDERR a duplicate ... The first command sends both standard out and standard error to the ...
    (comp.lang.perl.misc)
  • FAQ 8.25 How can I capture STDERR from an external command?
    ... both STDOUT and STDERR will go the same place as the ... script's STDOUT and STDERR, unless the systemcommand redirects them. ... You can also use file-descriptor redirection to make STDERR a duplicate ... The first command sends both standard out and standard error to the ...
    (comp.lang.perl.misc)