I've updated the patch/pretend-NMU (0.6.5-2.2) to include two additional changes (patch-4, patch-5 from arch). patch-4 fixes a bug where a fd can be removed from the set select() listens to even though there's still a listener for it, and patch-5 adds error check assertions to the return values of select() which were previously ignored. Patches for these additional changes attached, and the 0.6.5-2.2 pretend-NMU is available from the same location as the previous one above.
--- orig/sigcx/dispatch.cc +++ mod/sigcx/dispatch.cc @@ -22,6 +22,8 @@ #include <sys/time.h> #include <sys/types.h> #include <unistd.h> +#include <assert.h> +#include <errno.h> #include "sigcx/dispatch.h" @@ -181,6 +183,7 @@ Guard guard(mutex_); HandlerID id = get_new_handler_id(); + ++rd_fd_use_[fd]; FD_SET(fd, &rd_fds_); fd_handlers_.insert(make_pair(id, FileEvent(cb, Read, fd))); @@ -193,6 +196,7 @@ Guard guard(mutex_); HandlerID id = get_new_handler_id(); + ++wr_fd_use_[fd]; FD_SET(fd, &wr_fds_); fd_handlers_.insert(make_pair(id, FileEvent(cb, Write, fd))); @@ -204,6 +208,7 @@ { Guard guard(mutex_); HandlerID id = get_new_handler_id(); + ++ex_fd_use_[fd]; FD_SET(fd, &ex_fds_); fd_handlers_.insert(make_pair(id, FileEvent(cb, Except, fd))); @@ -244,12 +249,18 @@ { FileEvent& fevent = fd_it->second; - if (fevent.ev == Read && FD_ISSET(fevent.fd, &rd_fds_)) + if (fevent.ev == Read && --rd_fd_use_[fevent.fd] == 0) { FD_CLR(fevent.fd, &rd_fds_); - if (fevent.ev == Write && FD_ISSET(fevent.fd, &wr_fds_)) + rd_fd_use_.erase(fevent.fd); + } + if (fevent.ev == Write && --wr_fd_use_[fevent.fd] == 0) { FD_CLR(fevent.fd, &wr_fds_); - if (fevent.ev == Except && FD_ISSET(fevent.fd, &ex_fds_)) + wr_fd_use_.erase(fevent.fd); + } + if (fevent.ev == Except && --ex_fd_use_[fevent.fd] == 0) { FD_CLR(fevent.fd, &ex_fds_); + ex_fd_use_.erase(fevent.fd); + } fevent.deleted = true; }
--- orig/sigcx/dispatch.h +++ mod/sigcx/dispatch.h @@ -221,6 +221,7 @@ typedef std::multimap<TimerEvent, HandlerID> TMEventMap; typedef std::map<HandlerID, TMEventMap::iterator> TMHandlerMap; typedef std::map<HandlerID, FileEvent> FDHandlerMap; + typedef std::map<int, int> FDUseMap; Threads::Mutex mutex_; @@ -228,6 +229,10 @@ TMEventMap tm_events_; FDHandlerMap fd_handlers_; fd_set rd_fds_, wr_fds_, ex_fds_; + FDUseMap rd_fd_use_; + FDUseMap wr_fd_use_; + FDUseMap ex_fd_use_; + bool do_exit_; };
--- orig/sigcx/dispatch.cc +++ mod/sigcx/dispatch.cc @@ -360,7 +360,8 @@ if (tm_events_.size() == 0) { UnGuard unguard (mutex_); - select(FD_SETSIZE, &rd, &wr, &ex, 0); + int result = select(FD_SETSIZE, &rd, &wr, &ex, 0); + assert(result != -1 || errno == EINTR); } else { @@ -376,7 +377,8 @@ tv.tv_sec = timeout.tv_sec; tv.tv_usec = timeout.tv_usec; - select(FD_SETSIZE, &rd, &wr, &ex, &tv); + int result = select(FD_SETSIZE, &rd, &wr, &ex, &tv); + assert(result != -1 || errno == EINTR); } // check after select, we might have caught a signal