[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

res_send versus signals



There's a bug in src/lib/libc/net/res_send.c, res_send():

If, say, gethostbyaddr() is called in a program that has an active, high-
frequency interval timer, it is possible that the resolver will get stuck in a 
loop that never finishes, hanging the program.  This could happen if a packet 
is dropped on the way to/from the namserver:  

In the code fragment below, there's a check to see if select() was interrupted 
by a signal.  If it was, the select is restarted w/ the same timeout value as 
before.  If the interval timer ticks faster than the timeout value, the program 
will loop forever in a select-interrupted loop.

Proposed solution: when select is interrupted, it should restarted w/ a smaller 
timeout (ideally, the residual timeout count from the last call).
    
                        /*
                         * Wait for reply
                         */
                        timeout.tv_sec = (_resp->retrans << try);
                        if (try > 0)
                                timeout.tv_sec /= _resp->nscount;
                        if ((long) timeout.tv_sec <= 0)
                                timeout.tv_sec = 1;
                        timeout.tv_usec = 0;
    wait:
                        dsmaskp = (fd_set *)calloc(howmany(s+1, NFDBITS),
                                                   sizeof(fd_mask));
                        if (dsmaskp == NULL) {
                                res_close();
                                goto next_ns;
                        }
                        FD_SET(s, dsmaskp);
                        n = select(s+1, dsmaskp, (fd_set *)NULL,
                                   (fd_set *)NULL, &timeout);
                        free(dsmaskp);
                        if (n < 0) {
                                if (errno == EINTR)
                                        goto wait;
                                Perror(stderr, "select", errno);
                                res_close();
                                goto next_ns;
                        }



Visit your host, monkey.org