Ejemplo n.º 1
0
/*
 * Wrapper for poll(s, timeout).
 * Auto restarts with adjusted timeout if interrupted by
 * signal other than our wakeup signal.
 */
int NET_Timeout(int s, long timeout) {
    long prevtime = 0, newtime;
    struct timeval t;
    fdEntry_t *fdEntry = getFdEntry(s);

    /*
     * Check that fd hasn't been closed.
     */
    if (fdEntry == NULL) {
        errno = EBADF;
        return -1;
    }

    /*
     * Pick up current time as may need to adjust timeout
     */
    if (timeout > 0) {
        gettimeofday(&t, NULL);
        prevtime = t.tv_sec * 1000  +  t.tv_usec / 1000;
    }

    for(;;) {
        struct pollfd pfd;
        int rv;
        threadEntry_t self;

        /*
         * Poll the fd. If interrupted by our wakeup signal
         * errno will be set to EBADF.
         */
        pfd.fd = s;
        pfd.events = POLLIN | POLLERR;

        startOp(fdEntry, &self);
        rv = poll(&pfd, 1, timeout);
        endOp(fdEntry, &self);

        /*
         * If interrupted then adjust timeout. If timeout
         * has expired return 0 (indicating timeout expired).
         */
        if (rv < 0 && errno == EINTR) {
            if (timeout > 0) {
                gettimeofday(&t, NULL);
                newtime = t.tv_sec * 1000  +  t.tv_usec / 1000;
                timeout -= newtime - prevtime;
                if (timeout <= 0) {
                    return 0;
                }
                prevtime = newtime;
            }
        } else {
            return rv;
        }

    }
}
Ejemplo n.º 2
0
/*
 * Close or dup2 a file descriptor ensuring that all threads blocked on
 * the file descriptor are notified via a wakeup signal.
 *
 *      fd1 < 0    => close(fd2)
 *      fd1 >= 0   => dup2(fd1, fd2)
 *
 * Returns -1 with errno set if operation fails.
 */
static int closefd(int fd1, int fd2) {
    int rv, orig_errno;
    fdEntry_t *fdEntry = getFdEntry(fd2);
    if (fdEntry == NULL) {
        errno = EBADF;
        return -1;
    }

    /*
     * Lock the fd to hold-off additional I/O on this fd.
     */
    pthread_mutex_lock(&(fdEntry->lock));

    {
        /*
         * Send a wakeup signal to all threads blocked on this
         * file descriptor.
         */
        threadEntry_t *curr = fdEntry->threads;
        while (curr != NULL) {
            curr->intr = 1;
            pthread_kill( curr->thr, sigWakeup );
            curr = curr->next;
        }

        /*
         * And close/dup the file descriptor
         * (restart if interrupted by signal)
         */
        do {
            if (fd1 < 0) {
                rv = close(fd2);
            } else {
                rv = dup2(fd1, fd2);
            }
        } while (rv == -1 && errno == EINTR);

    }

    /*
     * Unlock without destroying errno
     */
    orig_errno = errno;
    pthread_mutex_unlock(&(fdEntry->lock));
    errno = orig_errno;

    return rv;
}
Ejemplo n.º 3
0
/*
 * Wrapper for select(s, timeout). We are using select() on Mac OS due to Bug 7131399.
 * Auto restarts with adjusted timeout if interrupted by
 * signal other than our wakeup signal.
 */
int NET_Timeout(int s, long timeout) {
    long prevtime = 0, newtime;
    struct timeval t, *tp = &t;
    fd_set fds;
    fd_set* fdsp = NULL;
    int allocated = 0;
    threadEntry_t self;
    fdEntry_t *fdEntry = getFdEntry(s);

    /*
     * Check that fd hasn't been closed.
     */
    if (fdEntry == NULL) {
        errno = EBADF;
        return -1;
    }

    /*
     * Pick up current time as may need to adjust timeout
     */
    if (timeout > 0) {
        /* Timed */
        struct timeval now;
        gettimeofday(&now, NULL);
        prevtime = now.tv_sec * 1000  +  now.tv_usec / 1000;
        t.tv_sec = timeout / 1000;
        t.tv_usec = (timeout % 1000) * 1000;
    } else if (timeout < 0) {
        /* Blocking */
        tp = 0;
    } else {
        /* Poll */
        t.tv_sec = 0;
        t.tv_usec = 0;
    }

    if (s < FD_SETSIZE) {
        fdsp = &fds;
        FD_ZERO(fdsp);
    } else {
        int length = (howmany(s+1, NFDBITS)) * sizeof(int);
        fdsp = (fd_set *) calloc(1, length);
        if (fdsp == NULL) {
            return -1;   // errno will be set to ENOMEM
        }
        allocated = 1;
    }
    FD_SET(s, fdsp);

    for(;;) {
        int rv;

        /*
         * call select on the fd. If interrupted by our wakeup signal
         * errno will be set to EBADF.
         */

        startOp(fdEntry, &self);
        rv = select(s+1, fdsp, 0, 0, tp);
        endOp(fdEntry, &self);

        /*
         * If interrupted then adjust timeout. If timeout
         * has expired return 0 (indicating timeout expired).
         */
        if (rv < 0 && errno == EINTR) {
            if (timeout > 0) {
                struct timeval now;
                gettimeofday(&now, NULL);
                newtime = now.tv_sec * 1000  +  now.tv_usec / 1000;
                timeout -= newtime - prevtime;
                if (timeout <= 0) {
                    if (allocated != 0)
                        free(fdsp);
                    return 0;
                }
                prevtime = newtime;
                t.tv_sec = timeout / 1000;
                t.tv_usec = (timeout % 1000) * 1000;
            }
        } else {
            if (allocated != 0)
                free(fdsp);
            return rv;
        }

    }
}