diff --git a/src/libthecore/fdwatch.cpp b/src/libthecore/fdwatch.cpp index 0c618d8..c717ff2 100644 --- a/src/libthecore/fdwatch.cpp +++ b/src/libthecore/fdwatch.cpp @@ -309,6 +309,20 @@ static int fdwatch_get_fdidx(LPFDWATCH fdw, socket_t fd) { return -1; } +static int fdwatch_get_maxfd(LPFDWATCH fdw) +{ + int i; + socket_t max_fd = 0; + + for (i = 0; i < fdw->nselect_fds; ++i) + { + if (fdw->select_fds[i] > max_fd) + max_fd = fdw->select_fds[i]; + } + + return static_cast(max_fd) + 1; +} + void fdwatch_add_fd(LPFDWATCH fdw, socket_t fd, void* client_data, int rw, int oneshot) { int idx = fdwatch_get_fdidx(fdw, fd); @@ -318,10 +332,13 @@ void fdwatch_add_fd(LPFDWATCH fdw, socket_t fd, void* client_data, int rw, int o } idx = fdw->nselect_fds; fdw->select_fds[fdw->nselect_fds++] = fd; - fdw->fd_rw[idx] = rw; - } else { - fdw->fd_rw[idx] |= rw; + fdw->fd_rw[idx] = 0; } + + fdw->fd_rw[idx] |= rw; + if (oneshot && (rw & FDW_WRITE)) + fdw->fd_rw[idx] |= FDW_WRITE_ONESHOT; + fdw->fd_data[idx] = client_data; if (rw & FDW_READ) @@ -354,6 +371,7 @@ void fdwatch_del_fd(LPFDWATCH fdw, socket_t fd) int fdwatch(LPFDWATCH fdw, struct timeval *timeout) { int r, i, event_idx; + int max_fd = fdwatch_get_maxfd(fdw); struct timeval tv; fdw->working_rfd_set = fdw->rfd_set; @@ -363,12 +381,12 @@ int fdwatch(LPFDWATCH fdw, struct timeval *timeout) { tv.tv_sec = 0; tv.tv_usec = 0; - r = select(0, &fdw->working_rfd_set, &fdw->working_wfd_set, (fd_set*) 0, &tv); + r = select(max_fd, &fdw->working_rfd_set, &fdw->working_wfd_set, (fd_set*) 0, &tv); } else { tv = *timeout; - r = select(0, &fdw->working_rfd_set, &fdw->working_wfd_set, (fd_set*) 0, &tv); + r = select(max_fd, &fdw->working_rfd_set, &fdw->working_wfd_set, (fd_set*) 0, &tv); } if (r == -1) @@ -404,7 +422,7 @@ int fdwatch_check_fd(LPFDWATCH fdw, socket_t fd) void * fdwatch_get_client_data(LPFDWATCH fdw, unsigned int event_idx) { int idx = fdw->select_rfdidx[event_idx]; - if (idx < 0 || fdw->nfiles <= idx) { + if (idx < 0 || fdw->nselect_fds <= idx) { return NULL; } return fdw->fd_data[idx]; @@ -413,7 +431,7 @@ void * fdwatch_get_client_data(LPFDWATCH fdw, unsigned int event_idx) int fdwatch_get_ident(LPFDWATCH fdw, unsigned int event_idx) { int idx = fdw->select_rfdidx[event_idx]; - if (idx < 0 || fdw->nfiles <= idx) { + if (idx < 0 || fdw->nselect_fds <= idx) { return 0; } return (int)fdw->select_fds[idx]; @@ -422,7 +440,7 @@ int fdwatch_get_ident(LPFDWATCH fdw, unsigned int event_idx) void fdwatch_clear_event(LPFDWATCH fdw, socket_t fd, unsigned int event_idx) { int idx = fdw->select_rfdidx[event_idx]; - if (idx < 0 || fdw->nfiles <= idx) { + if (idx < 0 || fdw->nselect_fds <= idx) { return; } socket_t rfd = fdw->select_fds[idx]; @@ -436,7 +454,7 @@ void fdwatch_clear_event(LPFDWATCH fdw, socket_t fd, unsigned int event_idx) int fdwatch_check_event(LPFDWATCH fdw, socket_t fd, unsigned int event_idx) { int idx = fdw->select_rfdidx[event_idx]; - if (idx < 0 || fdw->nfiles <= idx) { + if (idx < 0 || fdw->nselect_fds <= idx) { return 0; } socket_t rfd = fdw->select_fds[idx]; @@ -447,6 +465,11 @@ int fdwatch_check_event(LPFDWATCH fdw, socket_t fd, unsigned int event_idx) if (result & FDW_READ) { return FDW_READ; } else if (result & FDW_WRITE) { + if (fdw->fd_rw[idx] & FDW_WRITE_ONESHOT) { + fdw->fd_rw[idx] &= ~(FDW_WRITE | FDW_WRITE_ONESHOT); + FD_CLR(fd, &fdw->wfd_set); + FD_CLR(fd, &fdw->working_wfd_set); + } return FDW_WRITE; } return 0;