We were trying to check whether any events had really been
notified on an fd before calling evmap_io_active on it, but instead
we were checking for an event pointer, which was always true.
In practice, this patch shouldn't change much, since epoll_wait
shouldn't return an event unless there is actually an event going
on.
Spotted by an anonymous bug reporter on Sourceforge. Closes bug
3078425.
Remember, the code
int is_less_than(int a, unsigned b) {
return a < b;
}
is buggy, since the C integer promotion rules basically turn it into
int is_less_than(int a, unsigned b) {
return ((unsigned)a) < b;
}
and we really want something closer to
int is_less_than(int a, unsigned b) {
return a < 0 || ((unsigned)a) < b;
}
.
Suggested by an example from Ralph Castain
Jason Toffaletti discovered with helgrind that our signal handler was
messing with evsig_base, which can be set from lots of places in the
code. Ordinarly, we'd just stick a lock on it, except that it is
illegal (and genuinely error-prone) to call pthread_mutex_acquire()
from inside a signal handler.
The solution is to only store the fd we write to in a static variable,
write the signal number to the fd, and put evsig_cb in charge of
activating signal events.
I have no idea how we'll cope if we want to enable this to handle
siginfo (where available) in the future.
When using the signal.c signal backend, Libevent currently only allows
one event_base to actually receive signals at a time. (This has been
the behavior since at least 1.4 and probably much earlier.) Now, we
detect and warn if you're likely to be racing about which signal goes
to which thread.
We also add a lock to control modifications of the evsig_base field,
to avoid race conditions like those found by Jason Toffaletti.
Also, more comments. Comments are good.
The trick here is that if we already told the base to wake up, and it
hasn't woken up yet, we don't need to tell it to wake up again. This
should help lots with inherently multithreaded code like IOCP.
If threads queue callbacks while event_process_deferred_callbacks is
running, the loop may spin long enough to significantly skew timers.
A unit test stressing this behavior is also in this commit.
- Increment reference count of bufferevents before initiating overlapped
operations to prevent the destructor from being called while operations
are pending. The only portable way of canceling overlapped ops is to
close the socket.
- Translate error codes to WSA* codes.
- Better handling of errors.
- Add an interface to add and del "virtual" events. Because IOCP
bufferevents don't register any events with the base, the event loop
has no way of knowing they exist. This causes the loop to terminate
prematurely. event_base_{add,del}_virtual increment/decrement base's
event count so the loop runs while there are any enabled IOCP
bufferevents.
- Prevent evbuffer_{add,prepend}_buffer from moving read-pinned chains.
- Fix evbuffer_drain to handle read-pinned chains better.
- Raise the limit on WSABUFs from two to MAX_WSABUFS for overlapped reads.
This reverts commit fab50488fcb741884ccdfa7b83643eac3e5c9cbf.
The function was, on reflection, not important enough to break the feature
freeze, since it's trivial to build on your own.