Re: [dwm] input status text bug?

From: Anselm R. Garbe <arg_AT_suckless.org>
Date: Wed, 31 Oct 2007 09:28:33 +0100

Hi Ritesh,

On Tue, Oct 30, 2007 at 11:04:33PM -0400, Ritesh Kumar wrote:
> I used to run dwm using the following bash script:
>
> while true; do
> date;
> sleep 1;
> done | dwm
>
> ... and things used to run fine :).
>
> I changed it to:
>
> while true; do
> cat $HOME/.dwm/status_* ;
> date;
> sleep 1;
> done | dwm
>
> The status_* files contain text without trailing \n's.
> Surprisingly , the contents of the statusbar didn't change (only date, no
> other status text) ... even though the while loop outputs something like
> <some text> Tue Oct 30 22:46:56 EDT 2007
> <some text> Tue Oct 30 22:46:57 EDT 2007
> <some text> Tue Oct 30 22:46:58 EDT 2007
> ...

> My guess is that read() reads the status_* text and date in two successive
> calls causing the date to prevail till sleep 1 is done.

Well let's have a look at the relevant bits in the code:

(a) switch(r = read(STDIN_FILENO, stext, sizeof stext - 1)) {
                [...]
        default:
(b) for(stext[r] = '\0', p = stext + strlen(stext) - 1; p >= stext && *p == '\n'; *p-- = '\0');
(c) for(; p >= stext && *p != '\n'; --p);
(d) if(p > stext)
(e) strncpy(stext, p + 1, sizeof stext);
                [...]

(a) Reads the next bunch of stdin, beginning at stext[0] and
ending at stext[r].

(b) 0-terminates stext, and trims rightmost '\n' from right to left only.

(c) If p still does not point to stext, it now seeks for a '\n'
character leftwards.

(d) If during (c) such a '\n' character was found, it is the
begin of the last line which has been read.

(e) Hence, we copy the last line read only to stext, beginning
at the '\n' character + 1 to stext. It is 0-terminated already.

So in my eyes, assumed the complete output of the input script
is read, the code is correct and does what it is supposed
to do: it only displays the last line read from stdin (this might
be a bunch of data which is not '\n'-terminated yet during this read
round of course).

If you like to debug, you could add an

  fprintf(stderr, "'stext == %s'\n", stext);

in there between (c) and (d). Then we can make sure that your
guess is correct.

If the input is not read during one read call as you believe,
then at least there must be some flashing, because dwm will
actually render the <some text> at the status bar, but maybe
your system is really fast and you don't notice this.

> I went through the source code and fixed the status input handling code to
> make sure it flushes the input status text only if in encounters a '\n'. The
> patch is given... unfortunately it is over my (recently posted) status text
> patch. I moved the trimming of trailing \n's to another function setstext()
> (introduced by my status text patch)... however, the relevant code can be
> moved to the function run().
>
> What do you guys think... did I accidentally break something?

I see the problem in the above code, and also believe that your
solution is more correct. What scares me is, that it might seen
as valid input if someone feeds dwm with for example:

echo -n "foo"

during while... but we can fix this. Please lemme know if your
guess is correct through using the above fprintf-debug trick.

Regards,

-- 
 Anselm R. Garbe >< http://www.suckless.org/ >< GPG key: 0D73F361
Received on Wed Oct 31 2007 - 09:28:33 UTC

This archive was generated by hypermail 2.2.0 : Sun Jul 13 2008 - 15:03:37 UTC