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
> [email protected]
> 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
[email protected]
https://lists.sourceforge.net/lists/listinfo/dspam-devel