This is a discussion on ftpd.c poll() -> kqueue replacement within the mailing.openbsd.tech forums, part of the OpenBSD category; --> Hi tech@, Here's a diff that turns the poll() based accept loop with a kevent() based accept loop, it ...
| |||||||
| Register | FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read |
| ||||
| Hi tech@, Here's a diff that turns the poll() based accept loop with a kevent() based accept loop, it also replaces two malloc(n * m) with calloc(n, m) Gilles Index: ftpd.c ================================================== ================= RCS file: /cvs/src/libexec/ftpd/ftpd.c,v retrieving revision 1.179 diff -u -p -r1.179 ftpd.c --- ftpd.c 2007/07/27 14:12:46 1.179 +++ ftpd.c 2007/07/31 08:42:51 @@ -77,12 +77,15 @@ static const char rcsid[] = /* * FTP server. */ +#include <sys/types.h> #include <sys/param.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <sys/wait.h> #include <sys/mman.h> +#include <sys/event.h> +#include <sys/time.h> #include <netinet/in.h> #include <netinet/in_systm.h> @@ -115,7 +118,6 @@ static const char rcsid[] = #include <unistd.h> #include <util.h> #include <utmp.h> -#include <poll.h> #if defined(TCPWRAPPERS) #include <tcpd.h> @@ -280,6 +282,10 @@ usage(void) int main(int argc, char *argv[]) { + int kq = -1; + int *fds; + struct kevent kev[1]; + struct kevent *kevtable = NULL; socklen_t addrlen; int ch, on = 1, tos; char *cp, line[LINE_MAX]; @@ -287,6 +293,7 @@ main(int argc, char *argv[]) struct hostent *hp; struct sigaction sa; int error = 0; + int n; tzset(); /* in case no timezone database in ~ftp */ sigfillset(&allsigs); /* used to block signals while root */ @@ -394,10 +401,8 @@ main(int argc, char *argv[]) endpwent(); if (daemon_mode) { - int *fds, i, fd; - struct pollfd *pfds; + int i, fd; struct addrinfo hints, *res, *res0; - nfds_t n; /* * Detach from parent. @@ -420,14 +425,23 @@ main(int argc, char *argv[]) exit(1); } + /* + * open kqueue + */ + kq = kqueue(); + if (kq < 0) { + syslog(LOG_ERR, "failed to open kqueue"); + exit(1); + } + n = 0; for (res = res0; res; res = res->ai_next) n++; - fds = malloc(n * sizeof(int)); - pfds = malloc(n * sizeof(struct pollfd)); - if (!fds || !pfds) { - syslog(LOG_ERR, "%s", strerror(errno)); + fds = calloc(n, sizeof(int)); + kevtable = calloc(n, sizeof(struct kevent)); + if (fds == NULL || kevtable == NULL) { + syslog(LOG_ERR, "calloc: %m"); exit(1); } @@ -437,31 +451,32 @@ main(int argc, char *argv[]) */ n = 0; for (res = res0; res; res = res->ai_next) { - fds[n] = socket(res->ai_family, res->ai_socktype, + fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - if (fds[n] < 0) + if (fd < 0) continue; - - if (setsockopt(fds[n], SOL_SOCKET, SO_REUSEADDR, + syslog(LOG_ERR, "FD: %d", fd); + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) { - close(fds[n]); - fds[n] = -1; + close(fd); continue; } - if (bind(fds[n], res->ai_addr, res->ai_addrlen) < 0) { - close(fds[n]); - fds[n] = -1; + if (bind(fd, res->ai_addr, res->ai_addrlen) < 0) { + close(fd); continue; } - if (listen(fds[n], 32) < 0) { - close(fds[n]); - fds[n] = -1; + if (listen(fd, 32) < 0) { + close(fd); continue; } - pfds[n].fd = fds[n]; - pfds[n].events = POLLIN; + fds[n] = fd; + EV_SET(&kev[0], fd, EVFILT_READ, EV_ADD|EV_CLEAR, NULL, NULL, NULL); + syslog(LOG_ERR, "FD: %d/%d", kq, fd); + if (kevent(kq, &kev[0], 1, NULL, 0, 0) < 0) { + syslog(LOG_ERR, "%m"); + } n++; } freeaddrinfo(res0); @@ -479,32 +494,47 @@ main(int argc, char *argv[]) * children to handle them. */ while (1) { - if (poll(pfds, n, INFTIM) < 0) { + int ret; + + ret = kevent(kq, NULL, 0, kevtable, n, 0); + if (ret < 0) { if (errno == EINTR) continue; - syslog(LOG_ERR, "poll: %m"); + syslog(LOG_ERR, "kevent: %m"); exit(1); } - for (i = 0; i < n; i++) - if (pfds[i].revents & POLLIN) { - addrlen = sizeof(his_addr); - fd = accept(pfds[i].fd, - (struct sockaddr *)&his_addr, - &addrlen); - if (fd != -1) { - if (fork() == 0) - goto child; + for (i = 0; i < ret; i++) { + if (kevtable[i].flags & EV_ERROR) { + syslog(LOG_ERR, "kevent: %m"); + } + else { + addrlen = sizeof(his_addr); + fd = accept(kevtable[i].ident, + (struct sockaddr *)&his_addr, + &addrlen); + if (fd != -1) { + if (fork() == 0) + goto child; close(fd); } } + } } child: /* child */ (void)dup2(fd, STDIN_FILENO); (void)dup2(fd, STDOUT_FILENO); - for (i = 0; i < n; i++) - close(fds[i]); + + if (kevtable != NULL) + free(kevtable); + + if (fds != NULL) { + for (i = 0; i < n; i++) + close(fds[i]); + free(fds); + } + #if defined(TCPWRAPPERS) /* ..in the child. */ if (!check_host((struct sockaddr *)&his_addr)) -- sysadmin & coder @ http://www.evilkittens.org/ coder @ http://www.exalead.com/ [demime 1.01d removed an attachment of type application/pgp-signature] |