On Tue, Jan 01, 2019 at 09:56:42PM +0100, dspam-devel--- via Dspam-devel wrote: > Hello Edgar, > > > I am interested in this patch. Are you able to share this patch? > > -- > Kind Regards from Switzerland, > > Stevan Baji? > > On 01/01/2019 07:14, Edgar Pettijohn wrote: > > I have adapted the daemon to use kqueue instead of select. If anyone is > > interested in the patch. > > > > Thanks, > > > > Edgar > > > > _______________________________________________ > Dspam-devel mailing list > Dspam-devel@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/dspam-devel
I haven't integrated into the build system yet. I'm still on the fence if I'm going to use dspam or not. So I will probably test it out a bit before putting more effort into it. So basically this patch just replaces daemon_listen() with a new daemon_listen() and includes the sys/event.h header unconditionally. If it is of interest then I will gladly put forth the additional effort. Edgar
--- daemon.c 2012-04-11 13:48:33.000000000 -0500 +++ /home/edgar/dspam/dspam-3.10.2/src/daemon.c 2019-01-01 15:55:39.119888537 -0600 @@ -36,11 +36,13 @@ #define RSET(A) ( A && !strcmp(A, "RSET") ) +#include <err.h> #include <string.h> #include <stdlib.h> #include <ctype.h> #include <errno.h> #include <error.h> +#include <sys/event.h> /* for kqueue */ #include <sys/types.h> #include <sys/stat.h> #include <sys/socket.h> @@ -86,18 +88,17 @@ * RETURN VALUES * returns 0 on success */ - int daemon_listen(DRIVER_CTX *DTX) { struct sockaddr_in local_addr, remote_addr; THREAD_CTX *TTX = NULL; - fd_set master, read_fds; pthread_attr_t attr; - struct timeval tv; - int fdmax, yes = 1; + struct timespec to = { 10, 0 }; + struct kevent ev; + int yes = 1; int domain = 0; /* listening on domain socket? */ int listener; /* listener fd */ - int i; - int port = 24, queue = 32; /* default port and queue size */ + int port = 2424, queue = 32; /* default port and queue size */ + int kq, nev; signal(SIGPIPE, SIG_IGN); signal(SIGINT, process_signal); @@ -114,9 +115,10 @@ domain = 1; /* initialize */ - - FD_ZERO(&master); - FD_ZERO(&read_fds); + if ((kq = kqueue()) == -1) { + LOG(LOG_CRIT, ERR_DAEMON_KQ, strerror(errno)); + return(EFAILURE); + } pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); @@ -200,16 +202,12 @@ return(EFAILURE); } - FD_SET(listener, &master); - fdmax = listener; + EV_SET(&ev, listener, EVFILT_READ, EV_ADD|EV_ENABLE, 0, 0, 0); + kevent(kq, &ev, 1, NULL, 0, &to); /* Process new connections (until death or reload) */ for(;;) { - read_fds = master; - tv.tv_sec = 2; - tv.tv_usec = 0; - if (__daemon_run == 0) { close(listener); @@ -219,80 +217,80 @@ return 0; } - if (select(fdmax+1, &read_fds, NULL, NULL, &tv)>0) { - + nev = kevent(kq, NULL, 0, &ev, 1, &to); + if (nev == -1) + err(1, "kevent"); + if (nev == 0) + continue; + else { /* Process read-ready connections */ - - for(i=0;i<=fdmax;i++) { - if (FD_ISSET(i, &read_fds)) { - - /* Accept new connections */ - - if (i == listener) { - int newfd; - int addrlen = sizeof(remote_addr); - - if ((newfd = accept(listener, - (struct sockaddr *)&remote_addr, - (socklen_t *) &addrlen)) == -1) - { + if ((int)ev.ident == listener) { + /* Accept new connections */ + int newfd; + int addrlen = sizeof(remote_addr); + + if ((newfd = accept(listener, + (struct sockaddr *)&remote_addr, + (socklen_t *) &addrlen)) == -1) + { LOG(LOG_WARNING, ERR_DAEMON_ACCEPT, strerror(errno)); continue; #ifdef DEBUG - } else if (!domain) { - char buff[32]; - LOGDEBUG("connection id %d from %s.", newfd, + } else if (!domain) { + char buff[32]; + LOGDEBUG("connection id %d from %s.", newfd, #ifdef HAVE_INET_NTOA_R_2 - inet_ntoa_r(remote_addr.sin_addr, buff) + inet_ntoa_r(remote_addr.sin_addr, buff) #else - inet_ntoa_r(remote_addr.sin_addr, buff, sizeof(buff)) + inet_ntoa_r(remote_addr.sin_addr, buff, sizeof(buff)) #endif - ); + ); #endif - } - fcntl(newfd, F_SETFL, O_RDWR); - setsockopt(newfd,SOL_SOCKET,TCP_NODELAY,&yes,sizeof(int)); - - /* - * Since processing time varies, each new connection gets its own - * thread, so we create a new thread context and send it on its way - * - */ + } + fcntl(newfd, F_SETFL, O_RDWR); + setsockopt(newfd,SOL_SOCKET,TCP_NODELAY,&yes,sizeof(int)); - TTX = calloc(1, sizeof(THREAD_CTX)); - if (TTX == NULL) { - LOG(LOG_CRIT, ERR_MEM_ALLOC); - close(newfd); - continue; - } else { - TTX->sockfd = newfd; - TTX->DTX = DTX; - memcpy(&TTX->remote_addr, &remote_addr, sizeof(remote_addr)); - - increment_thread_count(); - if (pthread_create(&TTX->thread, - &attr, process_connection, (void *) TTX)) - { - decrement_thread_count(); - LOG(LOG_CRIT, ERR_DAEMON_THREAD, strerror(errno)); - close(TTX->sockfd); - free(TTX); - continue; - } - } - } /* if i == listener */ - } /* if FD_SET else */ - } /* for(i.. */ - } /* if (select)... */ + /* + * Since processing time varies, each new connection gets its own + * thread, so we create a new thread context and send it on its way + * + */ + + TTX = calloc(1, sizeof(THREAD_CTX)); + if (TTX == NULL) { + LOG(LOG_CRIT, ERR_MEM_ALLOC); + close(newfd); + /*continue? we are out of memory only bad things can happen*/ + __daemon_run = 0; + break; + } else { + TTX->sockfd = newfd; + TTX->DTX = DTX; + memcpy(&TTX->remote_addr, &remote_addr, sizeof(remote_addr)); + + increment_thread_count(); + if (pthread_create(&TTX->thread, + &attr, process_connection, (void *) TTX)) + { + decrement_thread_count(); + LOG(LOG_CRIT, ERR_DAEMON_THREAD, strerror(errno)); + close(TTX->sockfd); + close(TTX->kq); + free(TTX); + continue; + } + } /* TTX != NULL */ + } /* if ev.ident == listener */ + } /* nev > 0 */ } /* for(;;) */ /* Shutdown - we should never get here, but who knows */ close(listener); + close(kq); pthread_attr_destroy(&attr); return 0; } - /* * process_connection(void *ptr) * @@ -314,6 +312,7 @@ char *server_ident = _ds_read_attribute(agent_config, "ServerIdent"); THREAD_CTX *TTX = (THREAD_CTX *) ptr; AGENT_CTX *ATX = NULL; + struct kevent ev; char *input, *cmdline = NULL, *token, *ptrptr; buffer *message = NULL; char *parms=NULL, *p=NULL; @@ -323,7 +322,8 @@ char buf[1024]; int tries = 0; int argc = 0; - FILE *fd = 0; + int nev; + FILE *fd = NULL; if (_ds_read_attribute(agent_config, "ServerMode") && !strcasecmp(_ds_read_attribute(agent_config, "ServerMode"), "standard")) @@ -336,9 +336,13 @@ { server_mode = SSM_AUTO; } + /* Initialize this threads kqueue */ + if ((TTX->kq = kqueue()) == -1) { + LOG(LOG_CRIT, ERR_DAEMON_KQ, strerror(errno)); + goto CLOSE; + } /* Initialize a file descriptor hook for dspam to use as stdout */ - fd = fdopen(TTX->sockfd, "w"); if (!fd) { close(TTX->sockfd); @@ -521,11 +525,15 @@ tries++; if (tries>=3) { - struct timeval tv; - tv.tv_sec = 5; - tv.tv_usec = 0; - select(0, NULL, NULL, NULL, &tv); - goto CLOSE; + /* is this some sort of sleep? */ + EV_SET(&ev, 1, EVFILT_TIMER, EV_ADD|EV_ENABLE|EV_CLEAR, 0, 5000, 0); + for (;;) { + nev = kevent(TTX->kq, &ev, 1, NULL, 1, NULL); + if (nev > 0) + goto CLOSE; + else + continue; /* check for errors ? */ + } } } } @@ -850,6 +858,8 @@ pthread_mutex_unlock(&TTX->DTX->connections[locked]->lock); if (fd) fclose(fd); + if (TTX->kq) + close(TTX->kq); buffer_destroy(TTX->packet_buffer); if (message) buffer_destroy(message); @@ -1114,41 +1124,45 @@ */ char *daemon_getline(THREAD_CTX *TTX, int timeout) { - struct timeval tv; + struct timespec to = { (time_t)timeout, 0 }; + struct kevent ev; char *p, *q, *pop; char buf[1024]; int total_wait = 0; long recv_len; - fd_set fds; - int i; + int i, nev; + + EV_SET(&ev, TTX->sockfd, EVFILT_READ, EV_ADD|EV_ENABLE|EV_CLEAR, 0, 0, 0); + kevent(TTX->kq, &ev, 1, NULL, 0, &to); pop = pop_buffer(TTX); while(!pop && total_wait<timeout) { if (__daemon_run == 0) return NULL; total_wait++; - tv.tv_sec = 1; - tv.tv_usec = 0; - FD_ZERO(&fds); - FD_SET(TTX->sockfd, &fds); - i = select(TTX->sockfd+1, &fds, NULL, NULL, &tv); - if (i<=0) + + nev = kevent(TTX->kq, NULL, 0, &ev, 1, &to); + if (nev == -1) + err(1, "kevent"); + if (nev == 0) continue; + else { + recv_len = recv(TTX->sockfd, buf, sizeof(buf)-1, 0); + buf[recv_len] = 0; + if (recv_len == 0) + return NULL; - recv_len = recv(TTX->sockfd, buf, sizeof(buf)-1, 0); - buf[recv_len] = 0; - if (recv_len == 0) - return NULL; - for(p=q=buf,i=0;i<recv_len;i++) { - if (*q) { - *p = *q; - p++; + for(p=q=buf,i=0;i<recv_len;i++) { + if (*q) { + *p = *q; + p++; + } + q++; } - q++; + *p = 0; + buffer_cat(TTX->packet_buffer, buf); + pop = pop_buffer(TTX); } - *p = 0; - buffer_cat(TTX->packet_buffer, buf); - pop = pop_buffer(TTX); } #ifdef VERBOSE
--- language.h 2012-04-11 13:48:33.000000000 -0500 +++ /home/edgar/dspam/dspam-3.10.2/src/language.h 2019-01-01 15:49:00.517519528 -0600 @@ -130,6 +130,7 @@ #define ERR_DAEMON_THREAD "Thread creation failed: %s" #define ERR_DAEMON_FAIL "Daemon mode failed to start" #define ERR_DAEMON_TERMINATE "Daemon terminating on signal %d" +#define ERR_DAEMON_KQ "Could not create kqueue" /* LMTP (externally visible) info codes */
_______________________________________________ Dspam-devel mailing list Dspam-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/dspam-devel