Hello,

I don't thikn the shutdown call is to blame - I think it's the large pile
of code below.  i.e. everything below the if (shutdown(..)) below.  The
question is, what does it all do and does it actually work?  It appears to
be the 'drain' code, but given it often results in this message:

"Shutdown socket .. and read 0 lingering bytes in 2 sec."

then it would suggest it doesn't work.  The comments also suggest the 2
seconds is "guess work".

I've sent SECONDS_TO_LINGER and MAX_SECS_TO_LINGER to 0 and the problem
goes away, and I've seen this discussed elsewhere on the forum.

So, if this code isn't needed, why is it still there?  And if it is
needed, why does it seem not to work and what is the correct figure for
SECONDS_TO_LINGER?  If this is being performed inline then I'd suggest 2s
is far too long - clients don't want to wait 2s for a request to complete
(ideally, socket clean up should not be done in this thread if any linger
is required).


John


..
MAX_SECS_TO_LINGER= 30
SECONDS_TO_LINGER= 2
...
int jk_shutdown_socket(jk_sock_t sd, jk_logger_t *l)
{
    ...

    /* Shut down the socket for write, which will send a FIN
     * to the peer.
     */
    if (shutdown(sd, SHUT_WR)) {
        rc = jk_close_socket(sd, l);
        if (JK_IS_DEBUG_LEVEL(l))
            jk_log(l, JK_LOG_DEBUG, "Failed sending SHUT_WR for socket
%d", sd);
        errno = save_errno;
        JK_TRACE_EXIT(l);
        return rc;
    }

    do {
#ifdef HAVE_POLL
        struct pollfd fds;

        fds.fd = sd;
        fds.events = POLLIN;
#else
        fd_set rs;

        FD_ZERO(&rs);
        /* Read all data from the peer until we reach "end-of-file"
         * (FIN from peer) or we've exceeded our overall timeout. If the
         * backend does not send us bytes within 2 seconds
         * (a value pulled from Apache 1.3 which seems to work well),
         * close the connection.
         */
        FD_SET(sd, &rs);
        tv.tv_sec  = timeout / 1000;
        tv.tv_usec = (timeout % 1000) * 1000;
#endif
        rp = 0;
#ifdef HAVE_POLL
        if (poll(&fds, 1, timeout) > 0)
#else
        if (select((int)sd + 1, &rs, NULL, NULL, &tv) > 0)
#endif
        {
            do {
#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
                rc = recv(sd, &dummy[0], sizeof(dummy), 0);
                if (JK_IS_SOCKET_ERROR(rc))
                    JK_GET_SOCKET_ERRNO();
#else
                rc = read(sd, &dummy[0], sizeof(dummy));
#endif
                if (rc > 0)
                    rp += rc;
            } while (JK_IS_SOCKET_ERROR(rc) && (errno == EINTR || errno ==
EAGAIN));

            if (rc < 0)
                break;
        }
        else
            break;
        rd += rp;
        if (rp < sizeof(dummy)) {
            if (timeout > SECONDS_TO_LINGER) {
                /* Try once again with 1000 times smaller timeout
                 * In our case 2 msec.
                 */
                timeout = SECONDS_TO_LINGER;
                continue;
            }
            /* We have read less then size of buffer
             * It's a good chance there will be no more data
             * to read.
             */
            if ((rc = sononblock(sd))) {
                rc = jk_close_socket(sd, l);
                if (JK_IS_DEBUG_LEVEL(l))
                    jk_log(l, JK_LOG_DEBUG,
                           "error setting socket %d to nonblocking", sd);
                errno = save_errno;
                JK_TRACE_EXIT(l);
                return rc;
            }
            if (JK_IS_DEBUG_LEVEL(l))
                jk_log(l, JK_LOG_DEBUG,
                       "shutting down the read side of socket %d", sd);
            shutdown(sd, SHUT_RD);
            break;
        }
        timeout = SECONDS_TO_LINGER * 1000;
    } while (difftime(time(NULL), start) < MAX_SECS_TO_LINGER);

    rc = jk_close_socket(sd, l);
    if (JK_IS_DEBUG_LEVEL(l))
        jk_log(l, JK_LOG_DEBUG,
               "Shutdown socket %d and read %d lingering bytes in %d sec.",
               sd, rd, (int)difftime(time(NULL), start));
    errno = save_errno;
    JK_TRACE_EXIT(l);
    return rc;
}



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to