void process_debt(int fd) { /* After a short write, we finally can deliver the "debt" */ ssize_t ret; dpf("Selecting %d for writing because of debt %d\n", fd, fdinfo[fd].debt); send_was_interrupted2: ret = send(fd, fdinfo[fd].buff, fdinfo[fd].debt, 0); dpf(" sent %d bytes\n", ret); if (ret == 0) { fprintf(stderr, "send returned 0? Submit to codinghorror?\n"); close_fd(fd); return; } else if (ret < 0) { if(errno==EINTR) goto send_was_interrupted2; if(errno==EAGAIN) { fdinfo[fd].writeready=0; fdinfo[fd].we_should_epoll_for_writes=1; epoll_update(fd); } else { fprintf(stderr, "Why epoll hasn't told us that there would be error at sending?\n"); perror("send"); close_fd(fd); return; } } else { if (ret < fdinfo[fd].debt) { dpf(" short write at %d\n", fd); /* _Again_ short write. Need to remember the rest of the buffer somewhere. */ int l = fdinfo[fd].debt - ret; char* b = (char*)malloc(l); if (b == NULL) { perror("malloc"); close_fd(fd); return; } memcpy(b, fdinfo[fd].buff + ret, l); free(fdinfo[fd].buff); fdinfo[fd].buff = b; fdinfo[fd].debt = l; fdinfo[fd].we_should_epoll_for_writes=1; epoll_update(fd); dpf(" re-stored debt %d for %d\n", l, fd); } else { /* Now the debt is fulfilled */ free(fdinfo[fd].buff); fdinfo[fd].buff = NULL; fdinfo[fd].debt = 0; dpf(" debt is fulfilled for %d\n", fd); /* and we can start a new cycle */ fdinfo[fdinfo[fd].peerfd].we_should_epoll_for_reads = 1; epoll_update(fdinfo[fd].peerfd); } } }
int evfilt_socket_knote_create(struct filter *filt, struct knote *kn) { struct epoll_event ev; if (linux_get_descriptor_type(kn) < 0) return (-1); /* TODO: return EBADF? */ if (kn->kn_flags & KNFL_REGULAR_FILE) return (-1); /* Convert the kevent into an epoll_event */ kn->data.events = EPOLLOUT; if (kn->kev.flags & EV_ONESHOT || kn->kev.flags & EV_DISPATCH) kn->data.events |= EPOLLONESHOT; if (kn->kev.flags & EV_CLEAR) kn->data.events |= EPOLLET; memset(&ev, 0, sizeof(ev)); ev.events = kn->data.events; ev.data.ptr = kn; return epoll_update(EPOLL_CTL_ADD, filt, kn, &ev); }
int evfilt_read_knote_delete(struct filter *filt, struct knote *kn) { if (kn->kev.flags & EV_DISABLE) return (0); if ( ( kn->kn_flags & KNFL_REGULAR_FILE && kn->kdata.kn_eventfd != -1 ) == true ) { if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_DEL, kn->kdata.kn_eventfd, NULL) < 0) { dbg_perror("epoll_ctl(2)"); return (-1); } (void) close(kn->kdata.kn_eventfd); kn->kdata.kn_eventfd = -1; } else { return epoll_update(EPOLL_CTL_DEL, filt, kn, NULL); } // clang will complain about not returning a value otherwise return (-1); }
int evfilt_socket_knote_delete(struct filter *filt, struct knote *kn) { if (kn->kev.flags & EV_DISABLE) return (0); else return epoll_update(EPOLL_CTL_DEL, filt, kn, NULL); }
int evfilt_socket_knote_enable(struct filter *filt, struct knote *kn) { struct epoll_event ev; memset(&ev, 0, sizeof(ev)); ev.events = kn->data.events; ev.data.ptr = kn; return epoll_update(EPOLL_CTL_ADD, filt, kn, &ev); }
int evfilt_read_knote_create(struct filter *filt, struct knote *kn) { struct epoll_event ev; if (linux_get_descriptor_type(kn) < 0) return (-1); /* Convert the kevent into an epoll_event */ #if defined(HAVE_EPOLLRDHUP) kn->data.events = EPOLLIN | EPOLLRDHUP; #else kn->data.events = EPOLLIN; #endif if (kn->kev.flags & EV_ONESHOT || kn->kev.flags & EV_DISPATCH) kn->data.events |= EPOLLONESHOT; if (kn->kev.flags & EV_CLEAR) kn->data.events |= EPOLLET; memset(&ev, 0, sizeof(ev)); ev.events = kn->data.events; ev.data.ptr = kn; /* Special case: for regular files, add a surrogate eventfd that is always readable */ if (kn->kn_flags & KNFL_FILE) { int evfd; kn->kn_epollfd = filter_epfd(filt); evfd = eventfd(0, 0); if (evfd < 0) { dbg_perror("eventfd(2)"); return (-1); } if (eventfd_write(evfd, 1) < 0) { dbg_perror("eventfd_write(3)"); (void) close(evfd); return (-1); } kn->kdata.kn_eventfd = evfd; if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_ADD, kn->kdata.kn_eventfd, &ev) < 0) { dbg_printf("epoll_ctl(2): %s", strerror(errno)); return (-1); } kn->kn_registered = 1; return (0); } return epoll_update(EPOLL_CTL_ADD, filt, kn, &ev); }
int evfilt_read_knote_disable(struct filter *filt, struct knote *kn) { if (kn->kn_flags & KNFL_REGULAR_FILE) { if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_DEL, kn->kdata.kn_eventfd, NULL) < 0) { dbg_perror("epoll_ctl(2)"); return (-1); } return (0); } else { return epoll_update(EPOLL_CTL_DEL, filt, kn, NULL); } }
int evfilt_read_knote_enable(struct filter *filt, struct knote *kn) { struct epoll_event ev; memset(&ev, 0, sizeof(ev)); ev.events = kn->data.events; ev.data.ptr = kn; if (kn->kn_flags & KNFL_REGULAR_FILE) { if (epoll_ctl(kn->kn_epollfd, EPOLL_CTL_ADD, kn->kdata.kn_eventfd, &ev) < 0) { dbg_perror("epoll_ctl(2)"); return (-1); } return (0); } else { return epoll_update(EPOLL_CTL_ADD, filt, kn, &ev); } // clang will complain about not returning a value otherwise return (-1); }
int evfilt_socket_knote_disable(struct filter *filt, struct knote *kn) { return epoll_update(EPOLL_CTL_DEL, filt, kn, NULL); }