/*
* This file is part of DisOrder.
- * Copyright (C) 2004, 2005 Richard Kettlewell
+ * Copyright (C) 2004, 2005, 2007 Richard Kettlewell
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
int fd;
ev_fd_callback *callback;
void *u;
+ const char *what;
};
struct fdmode {
int ret;
int maxfd;
struct timeout *t, **tt;
+ struct stat sb;
xgettimeofday(&now, 0);
/* Handle timeouts. We don't want to handle any timeouts that are added
xsigprocmask(SIG_BLOCK, &ev->sigmask, 0);
if(n < 0) {
error(errno, "error calling select");
+ if(errno == EBADF) {
+ /* If there's a bad FD in the mix then check them all and log what we
+ * find, to ease debugging */
+ for(mode = 0; mode < ev_nmodes; ++mode) {
+ for(n = 0; n < ev->mode[mode].nfds; ++n) {
+ const int fd = ev->mode[mode].fds[n].fd;
+
+ if(FD_ISSET(fd, &ev->mode[mode].enabled)
+ && fstat(fd, &sb) < 0)
+ error(errno, "fstat %d (%s)", fd, ev->mode[mode].fds[n].what);
+ }
+ }
+ }
return -1;
}
if(n > 0) {
ev_fdmode mode,
int fd,
ev_fd_callback *callback,
- void *u) {
+ void *u,
+ const char *what) {
int n;
D(("registering %s fd %d callback %p %p", modenames[mode], fd,
ev->mode[mode].fds[n].fd = fd;
ev->mode[mode].fds[n].callback = callback;
ev->mode[mode].fds[n].u = u;
+ ev->mode[mode].fds[n].what = what;
if(fd > ev->mode[mode].maxfd)
ev->mode[mode].maxfd = fd;
ev->escape = 1;
nonblock(ev->sigpipe[n]);
cloexec(ev->sigpipe[n]);
}
- if(ev_fd(ev, ev_read, ev->sigpipe[0], signal_read, 0)) {
+ if(ev_fd(ev, ev_read, ev->sigpipe[0], signal_read, 0, "sigpipe read")) {
close_sigpipe(ev);
return -1;
}
int ev_listen(ev_source *ev,
int fd,
ev_listen_callback *callback,
- void *u) {
+ void *u,
+ const char *what) {
struct listen_state *l = xmalloc(sizeof *l);
D(("registering listener fd %d callback %p %p", fd, (void *)callback, u));
l->callback = callback;
l->u = u;
- return ev_fd(ev, ev_read, fd, listen_callback, l);
+ return ev_fd(ev, ev_read, fd, listen_callback, l, what);
}
int ev_listen_cancel(ev_source *ev, int fd) {
ev_writer *ev_writer_new(ev_source *ev,
int fd,
ev_error_callback *callback,
- void *u) {
+ void *u,
+ const char *what) {
ev_writer *w = xmalloc(sizeof *w);
D(("registering writer fd %d callback %p %p", fd, (void *)callback, u));
w->callback = callback;
w->u = u;
w->ev = ev;
- if(ev_fd(ev, ev_write, fd, writer_callback, w))
+ if(ev_fd(ev, ev_write, fd, writer_callback, w, what))
return 0;
ev_fd_disable(ev, ev_write, fd);
return w;
int fd,
ev_reader_callback *callback,
ev_error_callback *error_callback,
- void *u) {
+ void *u,
+ const char *what) {
ev_reader *r = xmalloc(sizeof *r);
D(("registering reader fd %d callback %p %p %p",
r->error_callback = error_callback;
r->u = u;
r->ev = ev;
- if(ev_fd(ev, ev_read, fd, reader_callback, r))
+ if(ev_fd(ev, ev_read, fd, reader_callback, r, what))
return 0;
return r;
}
/*
* This file is part of DisOrder.
- * Copyright (C) 2004 Richard Kettlewell
+ * Copyright (C) 2004, 2007 Richard Kettlewell
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
ev_fdmode mode,
int fd,
ev_fd_callback *callback,
- void *u);
+ void *u,
+ const char *what);
/* register a callback on a file descriptor */
int ev_fd_cancel(ev_source *ev,
int ev_listen(ev_source *ev,
int fd,
ev_listen_callback *callback,
- void *u);
+ void *u,
+ const char *what);
/* register a socket listener callback. @bind@ and @listen@ should
* already have been called. */
ev_writer *ev_writer_new(ev_source *ev,
int fd,
ev_error_callback *callback,
- void *u);
+ void *u,
+ const char *what);
/* create a new buffered writer, writing to @fd@. Calls @error@ if an
* error occurs. */
int fd,
ev_reader_callback *callback,
ev_error_callback *error_callback,
- void *u);
+ void *u,
+ const char *what);
/* register a new reader. @callback@ will be called whenever data is
* available. */
cloexec(fd);
c->tag = tags++;
c->ev = ev;
- c->w = ev_writer_new(ev, fd, writer_error, c);
- c->r = ev_reader_new(ev, fd, redirect_reader_callback, reader_error, c);
+ c->w = ev_writer_new(ev, fd, writer_error, c,
+ "client writer");
+ c->r = ev_reader_new(ev, fd, redirect_reader_callback, reader_error, c,
+ "client reader");
c->fd = fd;
c->reader = reader_callback;
c->l = l;
cloexec(fd);
l->name = name;
l->pf = pf;
- if(ev_listen(ev, fd, listen_callback, l)) exit(EXIT_FAILURE);
+ if(ev_listen(ev, fd, listen_callback, l, "server listener"))
+ exit(EXIT_FAILURE);
return fd;
}