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!
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.
Found by Sebastian Hahn.
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.
You could previously do this with evbuffer_peek() and some memcpys,
but it was a bit more work than most folks wanted to get into.
Closes sourceforge ticket 3108072
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.
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 .
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.
{Patch split out by nickm}