Example #1
0
int
evfilt_socket_copyout(struct kevent *dst, struct knote *src, void *ptr)
{
    struct epoll_event * const ev = (struct epoll_event *) ptr;

    epoll_event_dump(ev);
    memcpy(dst, &src->kev, sizeof(*dst));
#if defined(HAVE_EPOLLRDHUP)
    if (ev->events & EPOLLRDHUP || ev->events & EPOLLHUP)
        dst->flags |= EV_EOF;
#else
    if (ev->events & EPOLLHUP)
        dst->flags |= EV_EOF;
#endif
    if (ev->events & EPOLLERR)
        dst->fflags = 1; /* FIXME: Return the actual socket error */
          
    /* On return, data contains the the amount of space remaining in the write buffer */
    if (ioctl(dst->ident, SIOCOUTQ, &dst->data) < 0) {
            /* race condition with socket close, so ignore this error */
            dbg_puts("ioctl(2) of socket failed");
            dst->data = 0;
    }

    return (0);
}
Example #2
0
static int
epoll_update(int op, struct filter *filt, struct knote *kn, struct epoll_event *ev)
{
    dbg_printf("op=%d fd=%d events=%s", op, (int)kn->kev.ident, 
            epoll_event_dump(ev));
    if (epoll_ctl(filt->kf_pfd, op, kn->kev.ident, ev) < 0) {
        dbg_printf("epoll_ctl(2): %s", strerror(errno));
        return (-1);
    }

    return (0);
}
Example #3
0
int
evfilt_read_copyout(struct kevent *dst, struct knote *src, void *ptr)
{
    struct epoll_event * const ev = (struct epoll_event *) ptr;

    /* Special case: for regular files, return the offset from current position to end of file */
    if (src->kn_flags & KNFL_REGULAR_FILE) {
        memcpy(dst, &src->kev, sizeof(*dst));
        dst->data = get_eof_offset(src->kev.ident);

        if (dst->data == 0) {
            dst->filter = 0;    /* Will cause the kevent to be discarded */
            if (epoll_ctl(src->kn_epollfd, EPOLL_CTL_DEL, src->kdata.kn_eventfd, NULL) < 0) {
                dbg_perror("epoll_ctl(2)");
                return (-1);
            }

#if FIXME
            /* XXX-FIXME Switch to using kn_inotifyfd to monitor for IN_ATTRIB events
                         that may signify the file size has changed.

                         This code is not tested.
             */
            int inofd;
            char path[PATH_MAX];

            inofd = inotify_init();
            if (inofd < 0) {
                dbg_perror("inotify_init(2)");
                (void) close(inofd);
                return (-1);
            } 
            src->kdata.kn_inotifyfd = inofd;
            if (linux_fd_to_path(&path[0], sizeof(path), src->kev.ident) < 0)
                return (-1);
            if (inotify_add_watch(inofd, path, IN_ATTRIB) < 0) {
                dbg_perror("inotify_add_watch");
                return (-1);
            }
            if (epoll_ctl(src->kn_epollfd, EPOLL_CTL_ADD, src->kdata.kn_inotifyfd, NULL) < 0) {
                dbg_perror("epoll_ctl(2)");
                return (-1);
            }
            /* FIXME: race here, should we check the EOF status again ? */
#endif
        }

        return (0);
    }

    dbg_printf("epoll: %s", epoll_event_dump(ev));
    memcpy(dst, &src->kev, sizeof(*dst));
#if defined(HAVE_EPOLLRDHUP)
    if (ev->events & EPOLLRDHUP || ev->events & EPOLLHUP)
        dst->flags |= EV_EOF;
#else
    if (ev->events & EPOLLHUP)
        dst->flags |= EV_EOF;
#endif
    if (ev->events & EPOLLERR)
        dst->fflags = 1; /* FIXME: Return the actual socket error */
          
    if (src->kn_flags & KNFL_PASSIVE_SOCKET) {
        /* On return, data contains the length of the 
           socket backlog. This is not available under Linux.
         */
        dst->data = 1;
    } else {
        /* On return, data contains the number of bytes of protocol
           data available to read.
         */
        int i;
        if (ioctl(dst->ident, SIOCINQ, &i) < 0) {
            /* race condition with socket close, so ignore this error */
            dbg_puts("ioctl(2) of socket failed");
            dst->data = 0;
        } else {
            dst->data = i;
            if (dst->data == 0)
                dst->flags |= EV_EOF;
        }
    }

    return (0);
}
Example #4
0
int
evfilt_socket_copyout(struct filter *filt, 
            struct kevent *dst, 
            int nevents)
{
    struct epoll_event epevt[MAX_KEVENT];
    struct epoll_event *ev;
    struct knote *kn;
    int i, nret;

    for (;;) {
        nret = epoll_wait(filt->kf_pfd, &epevt[0], nevents, 0);
        if (nret < 0) {
            if (errno == EINTR)
                continue;
            dbg_perror("epoll_wait");
            return (-1);
        } else {
            break;
        }
    }

    for (i = 0, nevents = 0; i < nret; i++) {
        ev = &epevt[i];
        epoll_event_dump(ev);
        kn = knote_lookup(filt, ev->data.fd);
        if (kn != NULL) {
            memcpy(dst, &kn->kev, sizeof(*dst));
#if defined(HAVE_EPOLLRDHUP)
            if (ev->events & EPOLLRDHUP || ev->events & EPOLLHUP)
                dst->flags |= EV_EOF;
#else
            if (ev->events & EPOLLHUP)
                dst->flags |= EV_EOF;
#endif
            if (ev->events & EPOLLERR)
                dst->fflags = 1; /* FIXME: Return the actual socket error */
          
            if (kn->flags & KNFL_PASSIVE_SOCKET) {
                /* On return, data contains the length of the 
                   socket backlog. This is not available under Linux.
                 */
                dst->data = 1;
            } else {
                /* On return, data contains the number of bytes of protocol
                   data available to read.
                 */
                if (ioctl(dst->ident, 
                            (dst->filter == EVFILT_READ) ? SIOCINQ : SIOCOUTQ, 
                            &dst->data) < 0) {
                    /* race condition with socket close, so ignore this error */
                    dbg_puts("ioctl(2) of socket failed");
                    dst->data = 0;
                }
            }

            if (kn->kev.flags & EV_DISPATCH) {
                socket_knote_delete(filt->kf_pfd, kn->kev.ident);
                KNOTE_DISABLE(kn);
            } else if (kn->kev.flags & EV_ONESHOT) {
                socket_knote_delete(filt->kf_pfd, kn->kev.ident);
                knote_free(filt, kn);
            }

            nevents++;
            dst++;
        }
    }

    return (nevents);
}