X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=ircd%2Fengine_select.c;h=436f10baa1122b86007990d1c0fc922a919879e2;hb=refs%2Fheads%2Fupstream-ssl;hp=f09c7713c5466adaf4d2009d655d5aa9f09c4b8c;hpb=fda30451cac5936729c683d38a700f4928812c6f;p=ircu2.10.12-pk.git diff --git a/ircd/engine_select.c b/ircd/engine_select.c index f09c771..436f10b 100644 --- a/ircd/engine_select.c +++ b/ircd/engine_select.c @@ -15,44 +15,69 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * $Id$ + */ +/** @file + * @brief BSD sockets select() event engine. + * @version $Id$ */ #include "config.h" -#include "ircd_events.h" - -#include "ircd.h" -#include "ircd_log.h" -#include "s_debug.h" - /* On BSD, define FD_SETSIZE to what we want before including sys/types.h */ #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__bsdi__) # if !defined(FD_SETSIZE) -# define FD_SETSIZE MAXCONNECTIONS +# define FD_SETSIZE ((MAXCONNECTIONS)+4) # endif #endif -#include +#include "ircd_events.h" + +#include "ircd.h" +#include "ircd_log.h" +#include "s_debug.h" + +/* #include -- Now using assert in ircd_log.h */ #include +#include /* needed for bzero() on OS X */ #include #include #include #include #include -#define SELECT_ERROR_THRESHOLD 20 /* after 20 select errors, restart */ -#define ERROR_EXPIRE_TIME 3600 /* expire errors after an hour */ +#if FD_SETSIZE < (MAXCONNECTIONS + 4) +/* + * Sanity check + * + * All operating systems work when MAXCONNECTIONS <= 252. + * Most operating systems work when MAXCONNECTIONS <= 1020 and FD_SETSIZE is + * updated correctly in the system headers (on BSD systems sys/types.h might + * have abruptly redefined it so the check is still done), you might + * already need to recompile your kernel. + * For larger FD_SETSIZE your mileage may vary (kernel patches may be needed). + */ +# error FD_SETSIZE is too small or MAXCONNECTIONS too large. +#endif + +#define SELECT_ERROR_THRESHOLD 20 /**< after 20 select errors, restart */ +#define ERROR_EXPIRE_TIME 3600 /**< expire errors after an hour */ +/** Array of active Socket structures, indexed by file descriptor. */ static struct Socket* sockList[FD_SETSIZE]; +/** Maximum file descriptor currently used. */ static int highest_fd; +/** Global read event interest bitmap. */ static fd_set global_read_set; +/** Global write event interest bitmap. */ static fd_set global_write_set; +/** Number of recent errors from select(). */ static int errors = 0; +/** Periodic timer to forget errors. */ static struct Timer clear_error; -/* decrements the error count once per hour */ +/** Decrement the error count (once per hour). + * @param[in] ev Expired timer event (ignored). + */ static void error_clear(struct Event* ev) { @@ -60,7 +85,10 @@ error_clear(struct Event* ev) timer_del(ev_timer(ev)); } -/* initialize the select engine */ +/** Initialize the select() engine. + * @param[in] max_sockets Maximum number of file descriptors to support. + * @return Non-zero on success, or zero on failure. + */ static int engine_init(int max_sockets) { @@ -84,7 +112,11 @@ engine_init(int max_sockets) return 1; /* initialization successful */ } -/* Figure out what events go with a given state */ +/** Figure out what events go with a given state. + * @param[in] state %Socket state to consider. + * @param[in] events User-specified preferred event set. + * @return Actual set of preferred events. + */ static unsigned int state_to_events(enum SocketState state, unsigned int events) { @@ -107,7 +139,11 @@ state_to_events(enum SocketState state, unsigned int events) return 0; } -/* Toggle bits in the global fd sets appropriately */ +/** Set interest events in #global_read_set and #global_write_set as appropriate. + * @param[in] fd File descriptor to operate on. + * @param[in] clear Set of interest events to clear from socket. + * @param[in] set Set of interest events to set on socket. + */ static void set_or_clear(int fd, unsigned int clear, unsigned int set) { @@ -126,7 +162,10 @@ set_or_clear(int fd, unsigned int clear, unsigned int set) } } -/* add a socket to be listened on */ +/** Add a socket to the event engine. + * @param[in] sock Socket to add to engine. + * @return Non-zero on success, or zero on error. + */ static int engine_add(struct Socket* sock) { @@ -155,7 +194,10 @@ engine_add(struct Socket* sock) return 1; /* success */ } -/* socket switching to new state */ +/** Handle state transition for a socket. + * @param[in] sock Socket changing state. + * @param[in] new_state New state for socket. + */ static void engine_state(struct Socket* sock, enum SocketState new_state) { @@ -171,7 +213,10 @@ engine_state(struct Socket* sock, enum SocketState new_state) state_to_events(new_state, s_events(sock))); /* new state */ } -/* socket events changing */ +/** Handle change to preferred socket events. + * @param[in] sock Socket getting new interest list. + * @param[in] new_events New set of interesting events for socket. + */ static void engine_events(struct Socket* sock, unsigned int new_events) { @@ -187,7 +232,9 @@ engine_events(struct Socket* sock, unsigned int new_events) state_to_events(s_state(sock), new_events)); /* new events */ } -/* socket going away */ +/** Remove a socket from the event engine. + * @param[in] sock Socket being destroyed. + */ static void engine_delete(struct Socket* sock) { @@ -206,7 +253,9 @@ engine_delete(struct Socket* sock) highest_fd--; } -/* engine event loop */ +/** Run engine event loop. + * @param[in] gen Lists of generators of various types. + */ static void engine_loop(struct Generators* gen) { @@ -216,7 +265,7 @@ engine_loop(struct Generators* gen) int nfds; int i; int errcode; - size_t codesize; + socklen_t codesize; struct Socket *sock; while (running) { @@ -241,7 +290,7 @@ engine_loop(struct Generators* gen) /* Log the select error */ log_write(LS_SOCKET, L_ERROR, 0, "select() error: %m"); if (!errors++) - timer_add(&clear_error, error_clear, 0, TT_PERIODIC, + timer_add(timer_init(&clear_error), error_clear, 0, TT_PERIODIC, ERROR_EXPIRE_TIME); else if (errors > SELECT_ERROR_THRESHOLD) /* too many errors... */ server_restart("too many select errors"); @@ -354,8 +403,6 @@ engine_loop(struct Generators* gen) break; } - assert(s_fd(sock) == i); - gen_ref_dec(sock); /* we're done with it */ } @@ -363,6 +410,7 @@ engine_loop(struct Generators* gen) } } +/** Descriptor for select() event engine. */ struct Engine engine_select = { "select()", /* Engine name */ engine_init, /* Engine initialization function */