It was a peachy Sunday, Jan 26 2014, 22:05:25 when Marco Pfatschbacher <m...@mailq.de> wrote:
> On Sun, Jan 26, 2014 at 03:44:14PM -0500, ido...@gmail.com wrote: > > Hi misc@, > > From http://marc.info/?l=openbsd-cvs&m=133217901415880&w=2 > > > > "The ``sleep until we have a writer'' behaviour of an open() on a > > fifo does so with the file descriptor table locked, so if we are > > waiting for another thread to be our writer we will hang forever. > > > > Found this using zotero and firefox." > > > > This behavior indeed hangs latest FF+Zotero. Is it fixable? > > > I've been running into this recently myself. > What makes this worse, is that the process isn't even killable. hmm, it agrees to die here without a fuss... > Guenther tried to fix this, but it got backed out: > > http://anoncvs.estpak.ee/cgi-bin/cgit/openbsd-src/commit/?id=d8a387a9a09560b65562bc317ad63427bc9cb819 > this patch works for me. what exactly was the problem that made it necessary to revert it? > I was trying to look into this, but ran out of time :-( > > A workaround might be to patch either zotero or firefox, to > open the fifo with O_RDWR instead of O_WRONLY. > This way it won't block in open(). > > Here's my test program to trigger the issue. > > #include <err.h> > #include <fcntl.h> > #include <stdio.h> > #include <stdlib.h> > #include <unistd.h> > #include <pthread.h> > > #include <sys/types.h> > > void * > open_thread(void *threadid) > { > int fd; > > sleep(1); /* delay to let main run into FIFO open first */ > > printf("before open in thread\n"); > > if ((fd = open("/tmp/regfile", O_CREAT| O_RDWR, 0600)) < 0) > err(1, "open"); > > printf("after open in thread\n"); > > close(fd); > pthread_exit(NULL); > } > > int > main(int argc, char** argv) > { > int fd; > pthread_t thread; > long t; > > if (pthread_create(&thread, NULL, open_thread, (void *)t) != > 0) err(1, "pthread_create"); > > mkfifo("/tmp/block.fifo", 0600); > > printf("before blocking open in main\n"); > > if ((fd = open("/tmp/block.fifo", O_WRONLY)) < 0) > err(1, "open"); > > printf("after blocking open in main\n"); > > close(fd); > pthread_exit(NULL); > exit(0); > }