[dwm] broken pipes

From: Manuel Badzong <lists_AT_badzong.com>
Date: Sat, 25 Nov 2006 08:17:59 +0100

Hi

I just started using dwm. While setting things up, I encountered "broken
pipe" in the upper right corner. After reading the man page I found out,
that this is the status bar and "broken pipe" means that I'm using xdm
(by the way: the man page says that xdm closes stdin and stdio. AFAIK
they get redirected to /dev/null to avoid EBADF in .xsession. Not really
important but could be fixed). As most of you I ended up using a fifo to
get things working, but surprisingly I still got "broken pipe"? Skimming
trough the archives I found a few neat scripts to solve my problem.
Sadly none of them really satisfied me because I don't want a sleep
adjusted clock in the status bar. I would like to change the status at
any time to anything. Here's my solution (I didn't find this in the
archives. If this technique is already known, skip to the next part):

mkfifo dwm_pipe
dwm < dwm_pipe > dwm_pipe

This opens dwm_pipe for reading and writing and thus keeping the fifo
from returning EOF in case that we have no more writers left. Then you
can set and reset the status at any time with:

echo whatever > dwm_pipe

If dwm ever writes to stdout (does it?) I'll see it in the status bar
rather than in /dev/null.

Fine. But at that point I started to ask myself where the "broken pipe"
was coming from. Why should dwm receive SIGPIPE or why should errno get
set to EPIPE (wich actually both means "broken pipe" and only happens on
the writer side)? Is dwm trying to write to stdin? After reading main.c
I recognized that "broken pipe" actually means error or eof reading
stdin. This definitely should be fixed. Patch for dwm-2.3 supplied.

I mainly changed 5 little things in the main event loop:
+ I reordered the select statement which seemed a little cluttered (no
offense).
+ I replaced fgets with read (I hate this FILE* crap). If for some
reason you prefer ANSI C over UNIX IO use feof() to catch EOF.
+ On error or EOF the appropriate message is written to the status bar
indicating exactly what happened (e.g. EOF when redirected by [xkg]dm).
+ I removed the double checking of readin and FD_ISSET on stdin (as
FD_ISSET is tested anyway and properly set by select).
+ Finally I added a FD_ISSET check for xfd (I didn't read the whole code
but I think it's appropriate because changing the status bar doesn't
require procevent [is it?])

Compiled and tested on Linux and NetBSD. Regards, Manuel

--- dwm-2.3/main.c 2006-11-24 15:46:27.000000000 +0100
+++ my_dwm-2.3/main.c 2006-11-25 07:52:59.000000000 +0100
@@ -267,22 +267,29 @@
                 if(readin)
                         FD_SET(STDIN_FILENO, &rd);
                 FD_SET(xfd, &rd);
- r = select(xfd + 1, &rd, NULL, NULL, NULL);
- if((r == -1) && (errno == EINTR))
- continue;
- if(r > 0) {
- if(readin && FD_ISSET(STDIN_FILENO, &rd)) {
- readin = NULL != fgets(stext, sizeof(stext), stdin);
- if(readin)
- stext[strlen(stext) - 1] = 0;
- else
- strcpy(stext, "broken pipe");
- drawstatus();
+ if(select(xfd + 1, &rd, NULL, NULL, NULL) == -1) {
+ if(errno == EINTR)
+ continue;
+ else
+ eprint("select failed\n");
+ }
+ if(FD_ISSET(STDIN_FILENO, &rd)) {
+ switch(r = read(STDIN_FILENO, stext, sizeof(stext))) {
+ case -1:
+ strncpy(stext, strerror(errno), sizeof(stext));
+ readin = False;
+ break;
+ case 0:
+ strncpy(stext, "EOF", sizeof(stext));
+ readin = False;
+ break;
+ default:
+ stext[r-1] = 0;
                         }
+ drawstatus();
                 }
- else if(r < 0)
- eprint("select failed\n");
- procevent();
+ if(FD_ISSET(xfd, &rd))
+ procevent();
         }
         cleanup();
         XCloseDisplay(dpy);
Received on Sat Nov 25 2006 - 08:17:58 UTC

This archive was generated by hypermail 2.2.0 : Sun Jul 13 2008 - 14:32:44 UTC