Nick Mathewson [Fri, 10 Feb 2012 16:24:51 +0000 (11:24 -0500)]
In the kqueue backend, do not report EBADF as an EV_READ
We were doing this because of (correct) reports that NetBSD gives an
EBADF when you try to add the write side of a pipe for which the
read side has been closed. But on most kqueue platforms, that
doesn't happen, and on *all* kqueue platforms, reporting a
nonexistent fd (which we usually have if we have seen EBADF) as
readable tends to give programs a case of the vapors.
Nicholas Marriott wrote the original patch here; I did the comment
fixes.
Nick Mathewson [Mon, 6 Feb 2012 17:24:49 +0000 (12:24 -0500)]
Loop on filtering SSL reads until we are blocked or exhausted.
This is not a perfect fix, but it's much much better than the
current buggy behavior, which could lead to filtering SSL
connections that just stopped reading.
Based on ideas by Maseeb Abdul Qadir and Mark Ellzey.
Nick Mathewson [Fri, 27 Jan 2012 19:30:41 +0000 (14:30 -0500)]
Restore fast-path event_reinit() for slower backends
We used to use the needs_reinit flag in struct eventop to indicate
whether an event backend had shared state across a fork(), and
therefore would require us to construct a new event backend. But
when we realized that the signal notification fds and the thread
notification fds would always be shared across forks, we stopped
looking at it.
This patch restores the old behavior so that poll, select, and
win32select don't need to do a linear scan over all pending
fds/signals when they do a reinit. Their life is hard enough
already.
Nick Mathewson [Fri, 27 Jan 2012 18:54:05 +0000 (13:54 -0500)]
Make event_reinit() more robust and maintainable
Previously, event_reinit required a bunch of really dubious hacks,
and violated a lot of abstraction barriers to mess around with lists
of internal events and "pretend" to re-add them.
The new (and fairly well commented!) implementation tries to be much
smarter, by isolating the changes as much as possible to the backend
state, and minimizing the amount of abstraction violations.
Specifically, we now use event_del() to remove events we want to
remove, rather than futzing around with queues in event_reinit().
To avoid bogus calls to evsel->del(), we temporarily replace evsel
with a null-object stub.
Also, we now push the responsibility for calling evsel->add() down
into the evmap code, so that we don't actually need to unlink and
re-link all of our events.
Nick Mathewson [Tue, 24 Jan 2012 21:08:00 +0000 (16:08 -0500)]
When including an -internal.h header outside the main tree, do so early
Some of our unit tests and sample code need functions and structures
defined in an -internal.h header. But that can freak out OpenSolaris,
where stdio.h wants to define _FILE_OFFSET_BITS unless it's already
defined, and then evconfig-internal.h defines it. Regular users
should never ever use our -internal.h headers, so the solution is
to make sure that if we're going to use them ourselves, we do so
before system headers.
Nick Mathewson [Tue, 24 Jan 2012 19:33:10 +0000 (14:33 -0500)]
Make regression tests run over 3x faster.
This was mainly a matter of reducing timeouts and delays, paying
special attention to every test that took longer than a second to
finish.
We could do better here; IMO anything over .7 sec is probably too
long, but it's a big win as it is.
Remember, interactive computing is a big win over batch processing:
anything that makes you get up and walk away from the terminal might
as well be making you carry your punch cards over to the mainframe.
Nick Mathewson [Mon, 23 Jan 2012 22:59:16 +0000 (17:59 -0500)]
Fix a list corruption bug when using event_reinit() with signals present
While re-adding all the events, event_reinit() could add a signal
event, which could then cause evsig_add() to add the
base->sig.ev_signal event. Later on its merry path through
base->eventqueue, event_reinit() would find that same event and give
it to event_io_add a second time. This would make the ev_io_next
list for that fd become circular. Ouch!
Nick Mathewson [Mon, 9 Jan 2012 21:44:53 +0000 (16:44 -0500)]
Fix a race condition in the dns/bufferevent_connect_hostname test.
As originally written, the test would only pass if the accept()
callbacks for the evconnlistener were all invoked before the last of
the CONNECTED/ERROR callbacks for the connecting/resolving bufferevent
had its call to event_base_loopexit() complete. But this was only
accidentally true in 2.0, and might not be true at all in 2.1 where
we schedule event_base_once() callbacks more aggressively.
Nick Mathewson [Mon, 9 Jan 2012 16:49:41 +0000 (11:49 -0500)]
Make evconnlistener work around bug in older Linux when getting nmapped
Older Linuxes sometimes respond to some nmap probes by having accept()
return a success but with socklen 0. That can lead to confusing behavior
when you go to process the sockaddr.
Nick Mathewson [Wed, 7 Dec 2011 16:49:52 +0000 (11:49 -0500)]
Bypass event_add when using event_base_once() for a 0-sec timeout
Some people use event_base_once(EV_TIMEOUT) to make a callback get
called "immediately". But this is pretty roundabout: it uses the
timeout heap to immediately put the event onto the active queue, when
it could just use event_active. Additionally, it can lead to
surprising re-ordering behavior.
This patch changes event_base_once so it bypasses event_add() and
called event_active() directly on a pure-timeout event with an empty
timeout.
Nick Mathewson [Mon, 5 Dec 2011 20:02:27 +0000 (15:02 -0500)]
Be absolutely sure to clear pncalls before leaving event_signal_closure
I thought we'd fixed the cases where this could come up, but
apparently having an event_base_break() happen while processing
signal events could get us in trouble.
Found by Remi Gacogne. Sourceforge issue 3451433 .
Mark Ellzey [Thu, 17 Nov 2011 16:59:41 +0000 (11:59 -0500)]
Avoid spinning on OpenSSL reads
Previously, if some sender were generating data to read on an
OpenSSL connection as fast as we could process it, we could easily
wind up looping on an openssl do_read operation without ever
considering other sockets.
The difference between this and the original method in
consider_reading() is that it only loops for a single completed
*frame* instead of looping until fd is drained or an error condition
was triggered.