better error handling

master
Marc Alexander Lehmann 2007-11-06 00:10:04 +00:00
parent 06cd0f8c41
commit 66df0f5347
6 changed files with 157 additions and 84 deletions

85
ev.c
View File

@ -155,6 +155,51 @@ volatile double SIGFPE_REQ = 0.0f;
/*****************************************************************************/
static void (*syserr_cb)(void);
void ev_set_syserr_cb (void (*cb)(void))
{
syserr_cb = cb;
}
static void
syserr (void)
{
if (syserr_cb)
syserr_cb ();
else
{
perror ("libev");
abort ();
}
}
static void *(*alloc)(void *ptr, long size);
void ev_set_allocator (void *(*cb)(void *ptr, long size))
{
alloc = cb;
}
static void *
ev_realloc (void *ptr, long size)
{
ptr = alloc ? alloc (ptr, size) : realloc (ptr, size);
if (!ptr && size)
{
fprintf (stderr, "libev: cannot allocate %ld bytes, aborting.", size);
abort ();
}
return ptr;
}
#define ev_malloc(size) ev_realloc (0, (size))
#define ev_free(ptr) ev_realloc ((ptr), 0)
/*****************************************************************************/
typedef struct
{
WL head;
@ -225,31 +270,31 @@ ev_now (EV_P)
#define array_roundsize(base,n) ((n) | 4 & ~3)
#define array_needsize(base,cur,cnt,init) \
if (expect_false ((cnt) > cur)) \
{ \
int newcnt = cur; \
do \
{ \
newcnt = array_roundsize (base, newcnt << 1); \
} \
while ((cnt) > newcnt); \
\
base = realloc (base, sizeof (*base) * (newcnt)); \
init (base + cur, newcnt - cur); \
cur = newcnt; \
#define array_needsize(base,cur,cnt,init) \
if (expect_false ((cnt) > cur)) \
{ \
int newcnt = cur; \
do \
{ \
newcnt = array_roundsize (base, newcnt << 1); \
} \
while ((cnt) > newcnt); \
\
base = ev_realloc (base, sizeof (*base) * (newcnt)); \
init (base + cur, newcnt - cur); \
cur = newcnt; \
}
#define array_slim(stem) \
if (stem ## max < array_roundsize (stem ## cnt >> 2)) \
{ \
stem ## max = array_roundsize (stem ## cnt >> 1); \
base = realloc (base, sizeof (*base) * (stem ## max)); \
base = ev_realloc (base, sizeof (*base) * (stem ## max)); \
fprintf (stderr, "slimmed down " # stem " to %d\n", stem ## max);/*D*/\
}
#define array_free(stem, idx) \
free (stem ## s idx); stem ## cnt idx = stem ## max idx = 0;
ev_free (stem ## s idx); stem ## cnt idx = stem ## max idx = 0;
/*****************************************************************************/
@ -704,7 +749,9 @@ loop_fork (EV_P)
struct ev_loop *
ev_loop_new (int methods)
{
struct ev_loop *loop = (struct ev_loop *)calloc (1, sizeof (struct ev_loop));
struct ev_loop *loop = (struct ev_loop *)ev_malloc (sizeof (struct ev_loop));
memset (loop, 0, sizeof (struct ev_loop));
loop_init (EV_A_ methods);
@ -718,7 +765,7 @@ void
ev_loop_destroy (EV_P)
{
loop_destroy (EV_A);
free (loop);
ev_free (loop);
}
void
@ -1397,7 +1444,7 @@ once_cb (EV_P_ struct ev_once *once, int revents)
ev_io_stop (EV_A_ &once->io);
ev_timer_stop (EV_A_ &once->to);
free (once);
ev_free (once);
cb (revents, arg);
}
@ -1417,7 +1464,7 @@ once_cb_to (EV_P_ struct ev_timer *w, int revents)
void
ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg)
{
struct ev_once *once = malloc (sizeof (struct ev_once));
struct ev_once *once = ev_malloc (sizeof (struct ev_once));
if (!once)
cb (EV_ERROR | EV_READ | EV_WRITE | EV_TIMEOUT, arg);

14
ev.h
View File

@ -229,6 +229,20 @@ int ev_version_minor (void);
ev_tstamp ev_time (void);
/* Sets the allocation function to use, works like realloc.
* It is used to allocate and free memory.
* If it returns zero when memory needs to be allocated, the library might abort
* or take some potentially destructive action.
* The default is your system realloc function.
*/
void ev_set_allocator (void *(*cb)(void *ptr, long size));
/* set the callback function to call on a
* retryable syscall error
* (such as failed select, poll, epoll_wait)
*/
void ev_set_syserr_cb (void (*cb)(void));
# if EV_MULTIPLICITY
/* the default loop is the only one that handles signals and child watchers */
/* you can call this as often as you like */

View File

@ -51,11 +51,16 @@ epoll_modify (EV_P_ int fd, int oev, int nev)
static void
epoll_poll (EV_P_ ev_tstamp timeout)
{
int eventcnt = epoll_wait (epoll_fd, epoll_events, epoll_eventmax, ceil (timeout * 1000.));
int i;
int eventcnt = epoll_wait (epoll_fd, epoll_events, epoll_eventmax, ceil (timeout * 1000.));
if (eventcnt < 0)
return;
{
if (errno != EINTR)
syserr ();
return;
}
for (i = 0; i < eventcnt; ++i)
fd_event (
@ -68,9 +73,9 @@ epoll_poll (EV_P_ ev_tstamp timeout)
/* if the receive array was full, increase its size */
if (expect_false (eventcnt == epoll_eventmax))
{
free (epoll_events);
ev_free (epoll_events);
epoll_eventmax = array_roundsize (epoll_events, epoll_eventmax << 1);
epoll_events = malloc (sizeof (struct epoll_event) * epoll_eventmax);
epoll_events = ev_malloc (sizeof (struct epoll_event) * epoll_eventmax);
}
}
@ -89,7 +94,7 @@ epoll_init (EV_P_ int flags)
method_poll = epoll_poll;
epoll_eventmax = 64; /* intiial number of events receivable per poll */
epoll_events = malloc (sizeof (struct epoll_event) * epoll_eventmax);
epoll_events = ev_malloc (sizeof (struct epoll_event) * epoll_eventmax);
return EVMETHOD_EPOLL;
}
@ -99,7 +104,7 @@ epoll_destroy (EV_P)
{
close (epoll_fd);
free (epoll_events);
ev_free (epoll_events);
}
static void

View File

@ -85,7 +85,12 @@ kqueue_poll (EV_P_ ev_tstamp timeout)
kqueue_changecnt = 0;
if (res < 0)
return;
{
if (errno != EINTR)
syserr ();
return;
}
for (i = 0; i < res; ++i)
{
@ -118,9 +123,9 @@ kqueue_poll (EV_P_ ev_tstamp timeout)
if (expect_false (res == kqueue_eventmax))
{
free (kqueue_events);
ev_free (kqueue_events);
kqueue_eventmax = array_roundsize (kqueue_events, kqueue_eventmax << 1);
kqueue_events = malloc (sizeof (struct kevent) * kqueue_eventmax);
kqueue_events = ev_malloc (sizeof (struct kevent) * kqueue_eventmax);
}
}
@ -159,7 +164,7 @@ kqueue_init (EV_P_ int flags)
method_poll = kqueue_poll;
kqueue_eventmax = 64; /* intiial number of events receivable per poll */
kqueue_events = malloc (sizeof (struct kevent) * kqueue_eventmax);
kqueue_events = ev_malloc (sizeof (struct kevent) * kqueue_eventmax);
kqueue_changes = 0;
kqueue_changemax = 0;
@ -173,8 +178,8 @@ kqueue_destroy (EV_P)
{
close (kqueue_fd);
free (kqueue_events);
free (kqueue_changes);
ev_free (kqueue_events);
ev_free (kqueue_changes);
}
static void

View File

@ -75,27 +75,28 @@ poll_modify (EV_P_ int fd, int oev, int nev)
static void
poll_poll (EV_P_ ev_tstamp timeout)
{
int i;
int res = poll (polls, pollcnt, ceil (timeout * 1000.));
if (res > 0)
{
int i;
for (i = 0; i < pollcnt; ++i)
fd_event (
EV_A_
polls [i].fd,
(polls [i].revents & (POLLOUT | POLLERR | POLLHUP) ? EV_WRITE : 0)
| (polls [i].revents & (POLLIN | POLLERR | POLLHUP) ? EV_READ : 0)
);
}
else if (res < 0)
if (res < 0)
{
if (errno == EBADF)
fd_ebadf (EV_A);
else if (errno == ENOMEM)
else if (errno == ENOMEM && !syserr_cb)
fd_enomem (EV_A);
else if (errno != EINTR)
syserr ();
return;
}
for (i = 0; i < pollcnt; ++i)
fd_event (
EV_A_
polls [i].fd,
(polls [i].revents & (POLLOUT | POLLERR | POLLHUP) ? EV_WRITE : 0)
| (polls [i].revents & (POLLIN | POLLERR | POLLHUP) ? EV_READ : 0)
);
}
static int
@ -114,6 +115,6 @@ poll_init (EV_P_ int flags)
static void
poll_destroy (EV_P)
{
free (pollidxs);
free (polls);
ev_free (pollidxs);
ev_free (polls);
}

View File

@ -55,10 +55,10 @@ select_modify (EV_P_ int fd, int oev, int nev)
{
int new_max = (fd >> 5) + 1;
vec_ri = (unsigned char *)realloc (vec_ri, new_max * 4);
vec_ro = (unsigned char *)realloc (vec_ro, new_max * 4); /* could free/malloc */
vec_wi = (unsigned char *)realloc (vec_wi, new_max * 4);
vec_wo = (unsigned char *)realloc (vec_wo, new_max * 4); /* could free/malloc */
vec_ri = (unsigned char *)ev_realloc (vec_ri, new_max * 4);
vec_ro = (unsigned char *)ev_realloc (vec_ro, new_max * 4); /* could free/malloc */
vec_wi = (unsigned char *)ev_realloc (vec_wi, new_max * 4);
vec_wo = (unsigned char *)ev_realloc (vec_wo, new_max * 4); /* could free/malloc */
for (; vec_max < new_max; ++vec_max)
((uint32_t *)vec_ri)[vec_max] =
@ -77,6 +77,7 @@ select_modify (EV_P_ int fd, int oev, int nev)
static void
select_poll (EV_P_ ev_tstamp timeout)
{
int word, offs;
struct timeval tv;
int res;
@ -88,39 +89,39 @@ select_poll (EV_P_ ev_tstamp timeout)
res = select (vec_max * 32, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv);
if (res > 0)
{
int word, offs;
for (word = vec_max; word--; )
{
if (((uint32_t *)vec_ro) [word] | ((uint32_t *)vec_wo) [word])
for (offs = 4; offs--; )
{
int idx = word * 4 + offs;
unsigned char byte_r = vec_ro [idx];
unsigned char byte_w = vec_wo [idx];
int bit;
if (byte_r | byte_w)
for (bit = 8; bit--; )
{
int events = 0;
events |= byte_r & (1 << bit) ? EV_READ : 0;
events |= byte_w & (1 << bit) ? EV_WRITE : 0;
if (events)
fd_event (EV_A_ idx * 8 + bit, events);
}
}
}
}
else if (res < 0)
if (res < 0)
{
if (errno == EBADF)
fd_ebadf (EV_A);
else if (errno == ENOMEM)
else if (errno == ENOMEM && !syserr_cb)
fd_enomem (EV_A);
else if (errno != EINTR)
syserr ();
return;
}
for (word = vec_max; word--; )
{
if (((uint32_t *)vec_ro) [word] | ((uint32_t *)vec_wo) [word])
for (offs = 4; offs--; )
{
int idx = word * 4 + offs;
unsigned char byte_r = vec_ro [idx];
unsigned char byte_w = vec_wo [idx];
int bit;
if (byte_r | byte_w)
for (bit = 8; bit--; )
{
int events = 0;
events |= byte_r & (1 << bit) ? EV_READ : 0;
events |= byte_w & (1 << bit) ? EV_WRITE : 0;
if (events)
fd_event (EV_A_ idx * 8 + bit, events);
}
}
}
}
@ -143,10 +144,10 @@ select_init (EV_P_ int flags)
static void
select_destroy (EV_P)
{
free (vec_ri);
free (vec_ro);
free (vec_wi);
free (vec_wo);
ev_free (vec_ri);
ev_free (vec_ro);
ev_free (vec_wi);
ev_free (vec_wo);
}