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);

Reply via email to