From 9ea5b16bae42c9842f533e68ec85bf815c9bec9d Mon Sep 17 00:00:00 2001 From: Wouter Wijngaards Date: Thu, 16 Apr 2009 14:54:58 +0000 Subject: [PATCH] Windows winsock handler problem fixup. git-svn-id: file:///svn/unbound/trunk@1602 be551aaa-1e26-0410-a405-d3ace91eadb9 --- doc/Changelog | 1 + util/winsock_event.c | 34 ++++++++++++++++++++++++++++++---- util/winsock_event.h | 2 ++ 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/doc/Changelog b/doc/Changelog index b78f99690..f469428e3 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -2,6 +2,7 @@ - winsock event handler exit very quickly on signal, even if under heavy load. - iana portlist updated. + - fixup windows winsock handler reentrant problem. 14 April 2009: Wouter - bug #245: fix munin plugin, perform cleanup of stale lockfiles. diff --git a/util/winsock_event.c b/util/winsock_event.c index 83ee8ebc9..55cc23143 100644 --- a/util/winsock_event.c +++ b/util/winsock_event.c @@ -95,6 +95,18 @@ find_fd(struct event_base* base, int fd) return -1; } +/** Find ptr in base array */ +static int +find_entry(struct event_base* base, struct event* e) +{ + int i; + for(i=0; imax; i++) { + if(base->items[i] == e) + return i; + } + return -1; +} + void *event_init(uint32_t* time_secs, struct timeval* time_tv) { struct event_base* base = (struct event_base*)malloc( @@ -281,10 +293,15 @@ static int handle_select(struct event_base* base, struct timeval* wait) /* callbacks */ if(base->tcp_stickies) startidx = 0; /* process all events, some are sticky */ + for(i=startidx; ijust_checked = 1; verbose(VERB_CLIENT, "winsock_event signals"); for(i=startidx; iis_signal) { + eventlist[i]->just_checked = 0; handle_signal(eventlist[i]); } } @@ -296,10 +313,16 @@ static int handle_select(struct event_base* base, struct timeval* wait) for(i=startidx; iis_signal) { - /* not a network event at all */ - continue; - } + /* see if eventlist[i] is still valid and just checked from + * WSAWaitForEvents */ + if(find_entry(base, eventlist[i]) == -1) + continue; /* does not exist anymore */ + if(!eventlist[i]->just_checked) + continue; /* added by other callback */ + if(eventlist[i]->is_signal) + continue; /* not a network event at all */ + eventlist[i]->just_checked = 0; + if(WSAEnumNetworkEvents(eventlist[i]->ev_fd, waitfor[i], /* reset the event handle */ /*NULL,*/ /* do not reset the event handle */ @@ -448,6 +471,7 @@ void event_set(struct event *ev, int fd, short bits, ev->ev_callback = cb; fptr_ok(fptr_whitelist_event(ev->ev_callback)); ev->ev_arg = arg; + ev->just_checked = 0; ev->added = 0; } @@ -477,6 +501,7 @@ int event_add(struct event *ev, struct timeval *tv) ev->ev_base->items[ev->idx] = ev; ev->is_tcp = 0; ev->is_signal = 0; + ev->just_checked = 0; if((ev->ev_events&(EV_READ|EV_WRITE)) && ev->ev_fd != -1) { BOOL b=0; @@ -567,6 +592,7 @@ int event_del(struct event *ev) log_err("WSACloseEvent failed: %s", wsa_strerror(WSAGetLastError())); } + ev->just_checked = 0; ev->added = 0; return 0; } diff --git a/util/winsock_event.h b/util/winsock_event.h index 3a3c62d2c..340eb2ec0 100644 --- a/util/winsock_event.h +++ b/util/winsock_event.h @@ -188,6 +188,8 @@ struct event { * User created and user closed WSAEvent. Only signaled/unsigneled, * no read/write/distinctions needed. */ int is_signal; + /** used during callbacks to see which events were just checked */ + int just_checked; }; /** create event base */ -- 2.47.3