On Tue, Feb 7, 2012 at 1:47 PM, Nicholas Marriott <nicholas.marri...@gmail.com> wrote: > Forwarding this message to ML at Nick's request... > > Hi > > You may remember a few months ago you fixed a problem with kqueue and > EPIPE on pipes - I backported this fix to 1.4 and recently applied it to > OpenBSD. > > However, this is causing problems with Google Chrome. From what we can > gather it appears the problem is with EBADF - when kqueue returns EBADF > for an fd, libevent fires the read callback, same as for EPIPE. This > makes Chrome segfault somewhere in a huge mess of C++ that I can't > figure my way through.
Hm. So IIRC, we first added that EBADF in, it was (supposedly) because some kqueue implementations produced EBADF in response to one side of a pipe being closed while we were watching the other with kqueue. Do we know what platform or platforms this might have been? I'm not convinced atm that it's a real thing. I've attached a small test program that tries closing the read and the write side of a pipe, both before and after the point where it is added to the kqueue. Can we find any platform where it says "bad file descriptor"? If not, your fix would indeed seem to be the easy way around the present issue. yrs, -- Nick
#include <sys/types.h> #include <sys/event.h> #include <sys/time.h> #include <stdio.h> #include <errno.h> #include <unistd.h> #include <string.h> void dump_events(int r, const struct kevent *results) { int i; printf("%d events:\n", r); for (i=0;i<r;++i) { printf(" %d: filter=%x flags=%x", (int)results[i].ident, results[i].filter, results[i].flags); if (results[i].flags & EV_ERROR) { printf(" error=%d [%s]", (int)results[i].data, strerror(results[i].data)); } puts(""); } } int main(int argc, char **argv) { int kqfd, pipefd[4][2], r, i; struct kevent changes[4]; struct kevent results[16]; struct timespec ts = {1,0}; kqfd = kqueue(); if (kqfd < 0) { perror("kqueue"); return 1; } for (i=0;i<4;++i) { if (pipe(pipefd[i])<0) { perror("pipe"); return 1; } printf("pipefd[%d] = {%d,%d}\n", i, pipefd[i][0], pipefd[i][1]); } memset(changes, 0, sizeof(changes)); changes[0].ident = pipefd[0][0]; changes[0].filter = EVFILT_READ; changes[0].flags = EV_ADD; changes[1].ident = pipefd[1][0]; changes[1].filter = EVFILT_READ; changes[1].flags = EV_ADD; changes[2].ident = pipefd[2][1]; changes[2].filter = EVFILT_WRITE; changes[2].flags = EV_ADD; changes[3].ident = pipefd[3][1]; changes[3].filter = EVFILT_WRITE; changes[3].flags = EV_ADD; close(pipefd[0][1]); close(pipefd[2][0]); r = kevent(kqfd, changes, 4, results, 16, &ts); if (r<0) { perror("kevent"); return 1; } dump_events(r, results); close(pipefd[1][1]); close(pipefd[3][0]); r = kevent(kqfd, NULL, 0, results, 16, &ts); if (r<0) { perror("kevent"); return -1; } dump_events(r,results); return 0; }