Index: auto.def ================================================================== --- auto.def +++ auto.def @@ -537,10 +537,11 @@ cc-check-functions utime cc-check-functions usleep cc-check-functions strchrnul cc-check-functions pledge cc-check-functions backtrace +cc-check-functions kqueue # Check for getloadavg(), and if it doesn't exist, define FOSSIL_OMIT_LOAD_AVERAGE if {![cc-check-functions getloadavg]} { define FOSSIL_OMIT_LOAD_AVERAGE 1 msg-result "Load average support unavailable" Index: src/cgi.c ================================================================== --- src/cgi.c +++ src/cgi.c @@ -33,11 +33,16 @@ # include # include # include # include # include -# include +# if HAVE_KQUEUE +# include +# include +# else +# include +# endif #endif #ifdef __EMX__ typedef int socklen_t; #endif #include @@ -1819,15 +1824,25 @@ fossil_exit(1); #else int listener = -1; /* The server socket */ int connection; /* A socket for each individual connection */ int nRequest = 0; /* Number of requests handled so far */ - fd_set readfds; /* Set of file descriptors for select() */ + int hasdata = 0; /* select() / kevent() got a new connection */ socklen_t lenaddr; /* Length of the inaddr structure */ int child; /* PID of the child process */ int nchildren = 0; /* Number of child processes */ + unsigned waitUsec = 100000; /* Microseconds to wait in select() / kevent() */ +#if HAVE_KQUEUE + struct kevent event; /* The file descriptor we are monitoring */ + struct kevent tevent; /* The event that has triggered */ + int kq = -1; /* Queue descriptor return by kqueue() */ + int krc = 0; /* Return code from kevent() */ + struct timespec delay; /* How long to wait inside kevent() */ +#else + fd_set readfds; /* Set of file descriptors for select() */ struct timeval delay; /* How long to wait inside select() */ +#endif struct sockaddr_in inaddr; /* The socket address */ int opt = 1; /* setsockopt flag */ int iPort = mnPort; while( iPort<=mxPort ){ @@ -1888,23 +1903,52 @@ #endif if( system(zBrowser)<0 ){ fossil_warning("cannot start browser: %s\n", zBrowser); } } + +#if HAVE_KQUEUE + delay.tv_sec = 0; + delay.tv_nsec = 1000 * waitUsec; + kq = kqueue(); + if( kq==-1 ){ + fossil_fatal("kqueue: %s", strerror(errno)); + } + EV_SET(&event, listener, EVFILT_READ, EV_ADD, 0, 0, NULL); + krc = kevent(kq, &event, 1, NULL, 0, NULL); + if( krc==-1 || event.flags & EV_ERROR ){ + fossil_fatal("kevent: %s", strerror(krc==-1 ? errno : event.data)); + } +#endif + while( 1 ){ #if FOSSIL_MAX_CONNECTIONS>0 while( nchildren>=FOSSIL_MAX_CONNECTIONS ){ if( wait(0)>=0 ) nchildren--; } #endif +#if HAVE_KQUEUE + krc = kevent(kq, NULL, 0, &tevent, 1, &delay); + if( krc==-1 ){ + fossil_fatal("kevent: %s", strerror(errno)); + } + if( krc==1 ){ + hasdata = 1; + } +#else delay.tv_sec = 0; - delay.tv_usec = 100000; + delay.tv_usec = waitUsec; FD_ZERO(&readfds); assert( listener>=0 ); FD_SET( listener, &readfds); select( listener+1, &readfds, 0, 0, &delay); if( FD_ISSET(listener, &readfds) ){ + hasdata = 1; + } +#endif + if( hasdata ){ + hasdata = 0; lenaddr = sizeof(inaddr); connection = accept(listener, (struct sockaddr*)&inaddr, &lenaddr); if( connection>=0 ){ child = fork(); if( child!=0 ){