Thanks a lot for your reply! On 2010-09-20 12:29, Nick Mathewson wrote: > One possibility is that, when a non-retriable error occurs, the > callback is invoked with fd set to -1, and errno (LastSocketError) set > to the appropriate error. This behavior would break programs that > don't expect listeners to ever call the listener callback with a bad > fd, so it would have to be off by default, and enabled via an > LEV_OPT_* option. > > Another possibility is to allow code to register a separate error > callback for each listener that would get invoked when an error > occurred. This seems a little cleaner to me.
I'd be fine with both, but I would also prefer the second option. A separate callback for errors is how the rest of libevent already works. Would the attached patch work? Simon -- NAT64/DNS64 open-source --> http://ecdysis.viagenie.ca STUN/TURN server --> http://numb.viagenie.ca vCard 4.0 --> http://www.vcarddav.org
>From 0a5e1a39692dad552b08f7d4d133c5f220b639ff Mon Sep 17 00:00:00 2001 From: Simon Perreault <simon.perrea...@viagenie.ca> Date: Mon, 20 Sep 2010 12:47:39 -0400 Subject: [PATCH] Add error callback to evconnlistener --- include/event2/listener.h | 12 ++++++++++++ listener.c | 12 +++++++++++- 2 files changed, 23 insertions(+), 1 deletions(-) diff --git a/include/event2/listener.h b/include/event2/listener.h index 98ee886..5f34ff4 100644 --- a/include/event2/listener.h +++ b/include/event2/listener.h @@ -49,6 +49,14 @@ struct evconnlistener; */ typedef void (*evconnlistener_cb)(struct evconnlistener *, evutil_socket_t, struct sockaddr *, int socklen, void *); +/** + A callback that we invoke when a listener encounters a non-retriable error. + + @param listener The evconnlistener + @param user_arg the pointer passed to evconnlistener_new() + */ +typedef void (*evconnlistener_ecb)(struct evconnlistener *, void *); + /** Flag: Indicates that we should not make incoming sockets nonblocking * before passing them to the callback. */ #define LEV_OPT_LEAVE_SOCKETS_BLOCKING (1u<<0) @@ -114,6 +122,10 @@ struct event_base *evconnlistener_get_base(struct evconnlistener *lev); /** Return the socket that an evconnlistner is listening on. */ evutil_socket_t evconnlistener_get_fd(struct evconnlistener *lev); +/** Set an evconnlistener's error callback. */ +void evconnlistner_set_error_cb(struct evconnlistener *lev, + evconnlistener_ecb ecb); + #ifdef __cplusplus } #endif diff --git a/listener.c b/listener.c index 1b42281..ac56033 100644 --- a/listener.c +++ b/listener.c @@ -70,6 +70,7 @@ struct evconnlistener_ops { struct evconnlistener { const struct evconnlistener_ops *ops; evconnlistener_cb cb; + evconnlistener_ecb ecb; void *user_data; unsigned flags; }; @@ -281,6 +282,12 @@ event_listener_getbase(struct evconnlistener *lev) return event_get_base(&lev_e->listener); } +void evconnlistner_set_error_cb(struct evconnlistener *lev, + evconnlistener_ecb ecb) +{ + lev->ecb = ecb; +} + static void listener_read_cb(evutil_socket_t fd, short what, void *p) { @@ -303,7 +310,10 @@ listener_read_cb(evutil_socket_t fd, short what, void *p) err = evutil_socket_geterror(fd); if (EVUTIL_ERR_ACCEPT_RETRIABLE(err)) return; - event_sock_warn(fd, "Error from accept() call"); + if (lev->ecb != NULL) + lev->ecb(lev, lev->user_data); + else + event_sock_warn(fd, "Error from accept() call"); } #ifdef WIN32 -- 1.7.1