This is another bug fix that should have gone into my last commit. I

actually had this done at one point and lost it somewhere along the
line. Again, this is an honest to gosh bug fix only: no functionality
is changed.

- After a child broadcaster process dies or is killed, set its dom_pipe_fds
descriptors to -1 so that the 'READFD > 0' test in the select() loop
does the right thing.

Since descriptor values can be re-used, failure to do this can lead
to a situation where a descriptor for an RPC socket can be mistaken for
a pipe. If this happens, RPC sockets could be incorrectly handed off to
handle_children(), which would then clear the descriptor from the select()
descriptor mask and prevent svc_getreqset() from handling them. The end
result would be that some RPC events would go unserviced. Curiously,
the failures only happen intermittently.
This commit is contained in:
Bill Paul 1995-05-29 16:39:52 +00:00
parent a0ea7d345e
commit 236f9a3ab9
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=8853

View file

@ -96,7 +96,7 @@ void rpc_received __P((char *, struct sockaddr_in *, int ));
void broadcast __P((struct _dom_binding *));
int ping __P((struct _dom_binding *));
int tell_parent __P((char *, struct sockaddr_in *));
void handle_children __P(( int ));
void handle_children __P(( struct _dom_binding * ));
void reaper __P((int));
void terminate __P((int));
@ -461,7 +461,7 @@ char **argv;
default:
for(ypdb=ypbindlist; ypdb; ypdb=ypdb->dom_pnext) {
if (READFD > 0 && FD_ISSET(READFD, &fdsr)) {
handle_children(READFD);
handle_children(ypdb);
children--;
if (children == (MAX_CHILDREN - 1))
checkwork();
@ -486,22 +486,29 @@ checkwork()
/*
* Receive results from broadcaster. Don't worry about passing
* bogus info to rpc_received() -- it can handle it.
* bogus info to rpc_received() -- it can handle it. Note that we
* must be sure to invalidate the dom_pipe_fds descriptors here:
* since descriptors can be re-used, we have to make sure we
* don't mistake one of the RPC descriptors for one of the pipes.
* What's weird is that forgetting to invalidate the pipe descriptors
* doesn't always result in an error (otherwise I would have caught
* the mistake much sooner), even though logically it should.
*/
void handle_children(i)
int i;
void handle_children(ypdb)
struct _dom_binding *ypdb;
{
char buf[YPMAXDOMAIN + 1];
struct sockaddr_in addr;
if (read(i, &buf, sizeof(buf)) < 0)
if (read(READFD, &buf, sizeof(buf)) < 0)
syslog(LOG_WARNING, "could not read from child: %s", strerror(errno));
if (read(i, &addr, sizeof(struct sockaddr_in)) < 0)
if (read(READFD, &addr, sizeof(struct sockaddr_in)) < 0)
syslog(LOG_WARNING, "could not read from child: %s", strerror(errno));
close(i);
FD_CLR(i, &fdsr);
FD_CLR(i, &svc_fdset);
close(READFD);
FD_CLR(READFD, &fdsr);
FD_CLR(READFD, &svc_fdset);
READFD = WRITEFD = -1;
rpc_received((char *)&buf, &addr, 0);
}
@ -704,6 +711,9 @@ int force;
if (ypdb->dom_broadcast_pid) {
kill(ypdb->dom_broadcast_pid, SIGINT);
close(READFD);
FD_CLR(READFD, &fdsr);
FD_CLR(READFD, &svc_fdset);
READFD = WRITEFD = -1;
}
}