Пример #1
0
/**
 * Might call `svc_destroy(up7->xprt)`.
 *
 * @param[in] up7  Upstream LDM-7.
 * @retval    0    Success.
 */
static int
up7_run(
    Up7* const up7)
{
    const int     sock = up7->xprt->xp_sock;
    int           status;

    struct pollfd fds;
    fds.fd = sock;
    fds.events = POLLRDNORM;

    pthread_cleanup_push(funcCancelled, "up7_run");

    int initCancelState;
    (void)pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &initCancelState);

    for (;;) {
        udebug("up7_run(): Calling poll()");
        status = poll(&fds, 1, -1); // `-1` => indefinite timeout

        int cancelState;
        // (void)pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancelState);

        if (0 > status) {
            svc_destroy(up7->xprt);
            break;
        }
        if ((fds.revents & POLLERR) || (fds.revents & POLLNVAL)) {
            status = EIO;
            break;
        }
        if (fds.revents & POLLHUP) {
            status = 0;
            break;
        }
        if (fds.revents & POLLRDNORM) {
            udebug("up7_run(): Calling svc_getreqsock()");
            svc_getreqsock(sock); // calls `ldmprog_7()`
        }
        if (!FD_ISSET(sock, &svc_fdset)) {
            /*
             * The connection to the receiver was closed by the RPC layer =>
             * `svc_destroy(up7->xprt)` was called.
             */
            up7->xprt = NULL; // so others don't try to destroy it
            status = 0;
            break;
        }

        (void)pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &cancelState);
    }

    /*
     * In order to play nice with the caller, the cancelability state is
     * reverted to its value on entry.
     */
    (void)pthread_setcancelstate(initCancelState, &initCancelState);

    pthread_cleanup_pop(0);

    udebug("up7_run(): Returning %d", status);
    return status;
}
Пример #2
0
/**
 * Run an RPC server on a single socket (similar to svc_run(3RPC)). Runs until:
 *   1) The socket gets closed; or
 *   2) The timeout expires without any activity; or
 *   3) as_shouldSwitch() returns true; or
 *   4) An error occurs.
 * <p>
 * This function uses the "log" module to accumulate messages.
 *
 * @param sock              The connected socket.
 * @param timeout           The maximum amount of time to wait with no activity
 *                          on the socket in seconds.
 *
 * @retval 0                Success.  as_shouldSwitch() is true.
 * @retval EBADF            The socket isn't open.
 * @retval EINVAL           Invalid timeout value.
 * @retval ECONNRESET       RPC layer closed socket.  The RPC layer also
 *                          destroyed the associated SVCXPRT structure;
 *                          therefore, that object must not be subsequently
 *                          dereferenced.
 * @retval ETIMEDOUT        "timeout" time passed without any activity on
 *                          the socket.
 */ 
int
one_svc_run(
    const int       sock,
    const unsigned  timeout) 
{
    timestampt      canonicalTimeout;
    timestampt      selectTimeout;
    fd_set          fds;

    canonicalTimeout.tv_sec = timeout;
    canonicalTimeout.tv_usec = 0;
    selectTimeout = canonicalTimeout;

    FD_ZERO(&fds);
    FD_SET(sock, &fds);

    for (;;) {
        fd_set          readFds = fds;
        timestampt      before;
        int             selectStatus;

        (void)set_timestamp(&before);

        selectStatus = select(sock+1, &readFds, 0, 0, &selectTimeout);

        (void)exitIfDone(0); /* handles SIGTERM reception */

        if (selectStatus == 0)
            return ETIMEDOUT;

        if (selectStatus > 0) {
            /*
             * The socket is ready for reading. The following statement calls
             * `ldmprog_5()`, `ldmprog_6()`, or `ldmprog_7()`.
             */
            svc_getreqsock(sock);
            (void)exitIfDone(0);

            if (!FD_ISSET(sock, &svc_fdset)) {
                /*
                 * The RPC layer closed the socket and destroyed the associated
                 * SVCXPRT structure.
                 */
                 log_add("one_svc_run(): RPC layer closed connection");
                 return ECONNRESET;
            }

            if (as_shouldSwitch()) /* always false for upstream LDM-s */
                return 0;

            selectTimeout = canonicalTimeout; /* reset select(2) timeout */
        } /* socket is read-ready */
        else {
            if (errno != EINTR) {
                log_errno();
                log_add("one_svc_run(): select() error on socket %d", sock);
                return errno;
            }

            {
                timestampt      after;
                timestampt      diff;

                (void)set_timestamp(&after);

                /*
                 * Adjust select(2) timeout.
                 */
                diff = diff_timestamp(&after, &before);
                selectTimeout = diff_timestamp(&canonicalTimeout, &diff);
            }
        } /* select() returned -1 */
    } /* indefinite loop */

    return 0; // Eclipse wants to see a return
}