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.
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.
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.
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.
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.