diff options
author | wpaul <wpaul@FreeBSD.org> | 1996-11-30 22:38:44 +0000 |
---|---|---|
committer | wpaul <wpaul@FreeBSD.org> | 1996-11-30 22:38:44 +0000 |
commit | 7c59df49d939e5f564cc78e9a17c7d2393e11420 (patch) | |
tree | 11a2a1fc5ef8902ed9155bf6cb194e478f34da19 /usr.sbin/ypserv/yp_main.c | |
parent | 697c32345ed353ef71779fcebe2ad32f2747a771 (diff) | |
download | FreeBSD-src-7c59df49d939e5f564cc78e9a17c7d2393e11420.zip FreeBSD-src-7c59df49d939e5f564cc78e9a17c7d2393e11420.tar.gz |
This commit changes the YPPROC_ALL procecdure so that it handles requests
_without_ using fork().
The problem with YPPROC_ALL is that it transmits an entire map through
a TCP pipe as the result of a single RPC call. First of all, this requires
certain hackery in the XDR filter. Second, if the map being sent is
large, the server can end up spending lots of time in the XDR filter
sending to just the one client, while requests for other clients will
go unanswered.
My original solution for this was to fork() the request into a child
process which terminates after the map has been transmitted (or the
transfer is interrupted due to an error). This leaves the parent free
to handle other requests. But this solution is kind of lame: fork()
is relatively expensive, and we have to keep a cap on the number of
child processes to keep from swamping the system.
What we do now is grab control of the service transport handle and XDR
handle from the RPC library and send the records one at a time ourselves
instead of letting the RPC library do it. We send a record, then go
back to the svc_run() loop and select() on the socket. If select() says
we can still write data, we send the next record. Then we call
svc_getreqset() and handle other RPCs and loop around again. This way,
we can handle other RPCs between records.
We manage multiple YPPROC_ALL requests using a circular queue. When a
request is done, we dequeue it and destroy the handle. We also tag
each request with a ttl which is decremented whevever we run the queue
and a handle isn't serviced. This lets us nuke requests that have sat
idle for too long (if we didn't do this, we might run out of socket
descriptors.)
Now all I have to do is come up with an async resolver, and ypserv
won't need to fork() at all. :)
Note: these changes should not go into 2.2 unless they get a very
throrough shakedown before the final cutoff date.
Diffstat (limited to 'usr.sbin/ypserv/yp_main.c')
-rw-r--r-- | usr.sbin/ypserv/yp_main.c | 45 |
1 files changed, 3 insertions, 42 deletions
diff --git a/usr.sbin/ypserv/yp_main.c b/usr.sbin/ypserv/yp_main.c index 4d57d19..54a36d2 100644 --- a/usr.sbin/ypserv/yp_main.c +++ b/usr.sbin/ypserv/yp_main.c @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: yp_main.c,v 1.3 1996/05/01 02:39:34 wpaul Exp wpaul $ + * $Id: yp_main.c,v 1.6 1996/05/31 16:01:50 wpaul Exp $ */ /* @@ -66,7 +66,7 @@ #define _RPCSVC_CLOSEDOWN 120 #ifndef lint -static const char rcsid[] = "$Id: yp_main.c,v 1.3 1996/05/01 02:39:34 wpaul Exp wpaul $"; +static const char rcsid[] = "$Id: yp_main.c,v 1.6 1996/05/31 16:01:50 wpaul Exp $"; #endif /* not lint */ int _rpcpmstart; /* Started by a port monitor ? */ static int _rpcfdtype; @@ -79,7 +79,6 @@ static int _rpcfdtype; extern void ypprog_1 __P((struct svc_req, register SVCXPRT)); extern void ypprog_2 __P((struct svc_req, register SVCXPRT)); -extern int _rpc_dtablesize __P((void)); extern int _rpcsvcstate; /* Set when a request is serviced */ char *progname = "ypserv"; char *yp_dir = _PATH_YP; @@ -98,45 +97,6 @@ void _msgout(char* msg) syslog(LOG_ERR, msg); } -static void -yp_svc_run() -{ -#ifdef FD_SETSIZE - fd_set readfds; -#else - int readfds; -#endif /* def FD_SETSIZE */ - extern int forked; - int pid; - int fd_setsize = _rpc_dtablesize(); - - /* Establish the identity of the parent ypserv process. */ - pid = getpid(); - - for (;;) { -#ifdef FD_SETSIZE - readfds = svc_fdset; -#else - readfds = svc_fds; -#endif /* def FD_SETSIZE */ - switch (select(fd_setsize, &readfds, NULL, NULL, - (struct timeval *)0)) { - case -1: - if (errno == EINTR) { - continue; - } - perror("svc_run: - select failed"); - return; - case 0: - continue; - default: - svc_getreqset(&readfds); - if (forked && pid != getpid()) - exit(0); - } - } -} - static void unregister() { (void) pmap_unset(YPPROG, YPVERS); @@ -230,6 +190,7 @@ main(argc, argv) } load_securenets(); + yp_init_async(); #ifdef DB_CACHE yp_init_dbs(); #endif |