There are lots of things we do internally in bufferevents to indicate
"the user would like this operation to happen, but we aren't going to
try until some other condition goes away." Our logic here has gotten
entirely too complicated.
This patch tries to fix that by adding the idea of 'suspend flags' for
read and write. To say "don't bother reading or writing until
condition X no longer holds," bufferevent_suspend_read/write(bev,
BEV_SUSPEND_X). When X no longer holds, call
bufferevent_unsuspend_read/write(bev, BEV_SUSPEND_X).
Right now, only the read-watermark logic uses this.
William's original commit message:
Valgrind complains on startup because kq_init passes to kevent only
a partially initialized structure. The code doesn't expect kevent
to look at .fflags, .udata, or .data, I suppose, because it merely
tickles the kernel looking for an error response. But perhaps
that's unwarranted chuminess (notwithstanding that it's checking
for an OS X bug), and needless noise nonetheless.
There were a couple of places in the code where we manually kept lock
counts to make sure we never accessed resources without holding a
lock, and that we never released a lock we didn't have. The
lock-debugging code already puts counts on _every_ lock when lock
debugging is enabled, so there is no need to keep these counts around
otherwise. This patch rewrites the ASSERT_FOO_LOCKED macros to all
use a common EVLOCK_ASSERT_LOCKED().
We also teach the lock debugging code to keep track of who exactly
holds each lock, so that EVLOCK_ASSERT_LOCKED() means "locked by this
thread."
Original message:
evdns contains a bug related to thread lock.
enable thread lock by evthread_use_pthreads() will cause successive
evdns_base_resolve_ipv4() (and other resolve functions i think) to
hang on EVDNS_LOCK(base) after one or several successful call to
evdns_base_resolve_ipv4().
Previously, our default lock model kind of assumed that every lock was
potentially a read-write lock. This was a poor choice, since
read-write locks are far more expensive than regular locks, and so the
lock API should only use them when we can actually take advantage of
them. Neither our pthreads or win32 lock implementation provided rw
locks.
Now that we have a way (not currently used!) to indicate that we
really want a read-write lock, we shouldn't actually say "lock this
for reading" or "lock this for writing" unless we mean it.
Previously, there was no good way to request different kinds of lock
(say, read/write vs writeonly or recursive vs nonrecursive), or for a
lock function to signal failure (which would be important for a
trylock mode).
This patch revises the lock API to be a bit more useful. The older
lock calls are still supported for now.
We also add a debugging mode to catch common errors in using the
locking APIs.
It turns out that kqueue_dealloc wasn't calling evsig_dealloc()
(because it doesn't use the main signal handler logic) so the sh_old
array was leaking.
This patch also introduces a fix in evsig_dealloc() where we set
the sh_old array to NULL when we free it, so that main/fork can pass.
From evutil.c:
Some older BSDs (like OpenBSD up to 4.6) used to believe that
giving a numeric port without giving an ai_socktype was verboten.
We test for this so we can apply an appropriate workaround. If it
turns out that the bug is present, then:
- If nodename==NULL and servname is numeric, we build an answer
ourselves using evutil_getaddrinfo_common().
- If nodename!=NULL and servname is numeric, then we set
servname=NULL when calling getaddrinfo, and post-process the
result to set the ports on it.
We test for this bug at runtime, since otherwise we can't have the
same binary run on multiple BSD versions.
svn:r1550
I thought we had a way to do connect() that would never fail
immediately, but always wait for a moment before failing. It
turns out that on FreeBSD it can fail immediately. This is not
FreeBSD's fault, or even a real bug anywhere but in the unit test.
svn:r1549
Basically, we only want to report the 'connected' event because of
the socket connect() finishing when we have an actual socket
bufferevent; on an SSL bufferevent, 'connected' means 'SSL
connection finished.'
This isn't FreeBSD's fault: it just has a connect() that tends to
succeed pretty early.
svn:r1548
This patch from Chris Davis saves some callback depth, and adds proper
ref-counting to bufferevents when there's a deferred evbuffer callback
inflight. It could use a couple more comments to really nail down what
its invariants are.
svn:r1543
The entry points are evutil_getaddrinfo and evdns_getaddrinfo respectively.
There are fairly extensive unit tests.
I believe this code conforms to RFC3493 pretty closely, but there are
probably more issues. It should get tested on more platforms.
This code means we can dump the well-intentioned but weirdly-implemented
bufferevent_evdns and evutil_resolve code.
svn:r1537
Previously, event_base.activequeues was of type "array of pointers to
eventlist." This was pointless: none of the eventlists were allowed
to be NULL. Worse, it was inefficient:
- It made looking up an active event queue take two pointer
deferences instead of one, thus risking extra cache misses.
- It used more RAM than it needed to, because of the extra pointer
and the malloc overhead.
Also, this patch fixes a bug where we were saying
calloc(N,N*sizeof(X)) instead of calloc(N,sizeof(X)) when allocating
activequeues. That part, I'll backport.
Also, we warn and return -1 on failure to allocate activequeues,
rather than calling event_err.
svn:r1525