summaryrefslogtreecommitdiff
path: root/src/svc_run.c
diff options
context:
space:
mode:
authorThorsten Kukuk <kukuk@suse.de>2015-08-24 10:39:13 -0400
committerSteve Dickson <steved@redhat.com>2015-08-28 09:08:19 -0400
commitb2c9430f46c4ac848957fb8adaac176a3f6ac03f (patch)
tree1ec5caf4057960f45df755459b563a73664be506 /src/svc_run.c
parent1c77f7a869bdea2a34799d774460d1f9983d45f0 (diff)
downloadti-rpc-b2c9430f46c4ac848957fb8adaac176a3f6ac03f.tar.gz
Use poll() instead of select() in svc_run()
TI-RPC is using select() in svc_run(), while glibc and Solaris are using poll(). This has two drawbacks: poll() is much more efficient then select(), and with select() we are limited to 1024 open filehandles. And applications replacing svc_run on Linux don't work, since they expect svc_pollfd and svc_max_pollfd. Attached patch changes this. It's full backward compatible, API and ABI, so e.g. current rpcbind will continue to work and compile. The only problem could arrive, that we can have more than 1024 open filehandles and applications ignoring higher ones. Reviewed-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Thorsten Kukuk <kukuk@thkukuk.de> Signed-off-by: Steve Dickson <steved@redhat.com>
Diffstat (limited to 'src/svc_run.c')
-rw-r--r--src/svc_run.c78
1 files changed, 51 insertions, 27 deletions
diff --git a/src/svc_run.c b/src/svc_run.c
index 783b1dc..f40314b 100644
--- a/src/svc_run.c
+++ b/src/svc_run.c
@@ -34,10 +34,11 @@
#include <reentrant.h>
#include <err.h>
#include <errno.h>
-#include <rpc/rpc.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
+#include <sys/poll.h>
+
#include <rpc/rpc.h>
#include "rpc_com.h"
@@ -46,33 +47,54 @@
void
svc_run()
{
- fd_set readfds, cleanfds;
- struct timeval timeout;
- extern rwlock_t svc_fd_lock;
+ int i;
+ struct pollfd *my_pollfd = NULL;
+ int last_max_pollfd = 0;
+
+ for (;;) {
+ int max_pollfd = svc_max_pollfd;
+ if (max_pollfd == 0 && svc_pollfd == NULL)
+ break;
+
+ if (last_max_pollfd != max_pollfd)
+ {
+ struct pollfd *new_pollfd
+ = realloc (my_pollfd, sizeof (struct pollfd) * max_pollfd);
+
+ if (new_pollfd == NULL)
+ {
+ warn ("svc_run: - out of memory");
+ break;
+ }
+
+ my_pollfd = new_pollfd;
+ last_max_pollfd = max_pollfd;
+ }
+
+ for (i = 0; i < max_pollfd; ++i)
+ {
+ my_pollfd[i].fd = svc_pollfd[i].fd;
+ my_pollfd[i].events = svc_pollfd[i].events;
+ my_pollfd[i].revents = 0;
+ }
+ switch (i = poll (my_pollfd, max_pollfd, -1))
+ {
+ case -1:
+ if (errno == EINTR)
+ continue;
+ warn ("svc_run: - poll failed");
+ break;
+ case 0:
+ continue;
+ default:
+ svc_getreq_poll (my_pollfd, i);
+ continue;
+ }
+ break;
+ }
- for (;;) {
- rwlock_rdlock(&svc_fd_lock);
- readfds = svc_fdset;
- cleanfds = svc_fdset;
- rwlock_unlock(&svc_fd_lock);
- timeout.tv_sec = 30;
- timeout.tv_usec = 0;
- switch (select(svc_maxfd+1, &readfds, NULL, NULL, &timeout)) {
- case -1:
- FD_ZERO(&readfds);
- if (errno == EINTR) {
- continue;
- }
- warn("svc_run: - select failed");
- return;
- case 0:
- __svc_clean_idle(&cleanfds, 30, FALSE);
- continue;
- default:
- svc_getreqset(&readfds);
- }
- }
+ free (my_pollfd);
}
/*
@@ -85,6 +107,8 @@ svc_exit()
extern rwlock_t svc_fd_lock;
rwlock_wrlock(&svc_fd_lock);
- FD_ZERO(&svc_fdset);
+ free (svc_pollfd);
+ svc_pollfd = NULL;
+ svc_max_pollfd = 0;
rwlock_unlock(&svc_fd_lock);
}