Strange pager (less, more) behavior
- From: Dave Ulrick <ulrick@xxxxxxxxxxxxxxxx>
- Date: Tue, 28 Mar 2006 23:34:01 +0000 (UTC)
Hi,
Presently, I'm developing a set of C programs that run via the command
line and exclusively use standard C library stream I/O: fopen, fputs,
fprintf, fclose, etc.. As a convenience to the user, I allow many of
the output files to be defaulted to stdout or stderr. For instance,
a message log file might default to stderr. My file open logic for
such files amounts to something like this:
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.
However, I've noticed on my Linux 2.6.9 (and above) PCs that at
least some of my programs sometimes gets involved in a rather strange
bit of (mis)behavior when I pipe its output to a pager such as 'less'
or 'more'. When I do this, my command line looks something like
this:
$ ./myprogram 2>&1 | less
99.44% of the time, this works perfectly, but every once in a while,
the pager doesn't appear. Instead, 'bash' gives me these messages:
[1]+ Stopped ./myprogram 2>&1 | less
as though I'd pressed Ctrl-Z to stop the pipeline even though I've not
pressed any such key. 'ps auxw' reveals that my program has completed
(i.e., no process exists that has my program's name), but that 'less'
is in 'T' (traced or stopped) status. If I bring up 'gdb' and attach
it to the stopped 'less' process (foregrounding 'less' after attaching
it), I always see that 'less' is waiting in a call to tcsetattr()
with the TCSADRAIN flag (the 'less' function that calls tcsetattr() is
named raw_mode()). This flag indicates that the new terminal settings
are to take effect after pending I/O to the terminal has completed.
Since my program has finished running, the I/O that's expected by 'less'
is never going to happen, so it waits indefinitely until someone (the
Linux kernel) sends it a SIGSTOP (or SIGTSTP?) signal. When I issue 'fg',
'less' appears, complete with my program's output.
So, when this problem occurs, my program runs to completion, but 'less'
fails to appear, and instead is put into a "stopped" state. I've also
seen this problem with 'more' but not with 'most', so it's not just a
'less' problem. I've seen this behavior with Linux 2.6.9, 2.6.10,
and 2.6.16, but I've never seen it with Linux 2.6.5. It occurs with
bash 2.05b and 3.1, or with less 382 or 394. It also occurs with the
'more' that came with the util-linux-2.12 RPM that shipped with Fedora
Core 2. I've seen similar behavior involving a pager such as 'less'
with other programs such as 'grep'. The problem occurs in at least
two terminal emulators: konsole and xterm. Also, I've seen it happen
in a virtual console (i.e., outside of X11). In addition to 'bash',
I've also recreated the problem in AT&T ksh.
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. 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.
Finally, if this is a kernel bug or configuration error, I'd appreciate
some guidance on how I might work around it or fix it. Am I correct
that the kernel, bash, or some other process is issuing SIGSTOP against
'less' on account of the long wait in tcsetattr()? The PCs that suffer
from the problem started out as Fedora Core 2 and have been upgraded
with Linux 2.6.16, Bash 3.1, and less 394.
Thanks,
Dave
--
Dave Ulrick
Email: d-ulrick@xxxxxxx
Web: http://www.niu.edu/~ulrick/
.
- Follow-Ups:
- Re: Strange pager (less, more) behavior
- From:
- Re: Strange pager (less, more) behavior
- From: Måns Rullgård
- Re: Strange pager (less, more) behavior
- Prev by Date: Re: what's the relation among wxWidgets,xWindows and GTK+?
- Next by Date: Re: what's the relation among wxWidgets,xWindows and GTK+?
- Previous by thread: what's the relation among wxWidgets,xWindows and GTK+?
- Next by thread: Re: Strange pager (less, more) behavior
- Index(es):
Relevant Pages
|