|
|
@ -53,6 +53,10 @@ struct uv__stream_select_s { |
|
|
|
int fake_fd; |
|
|
|
int int_fd; |
|
|
|
int fd; |
|
|
|
fd_set* sread; |
|
|
|
size_t sread_sz; |
|
|
|
fd_set* swrite; |
|
|
|
size_t swrite_sz; |
|
|
|
}; |
|
|
|
#endif /* defined(__APPLE__) */ |
|
|
|
|
|
|
@ -131,8 +135,6 @@ static void uv__stream_osx_select(void* arg) { |
|
|
|
uv_stream_t* stream; |
|
|
|
uv__stream_select_t* s; |
|
|
|
char buf[1024]; |
|
|
|
fd_set sread; |
|
|
|
fd_set swrite; |
|
|
|
int events; |
|
|
|
int fd; |
|
|
|
int r; |
|
|
@ -153,17 +155,17 @@ static void uv__stream_osx_select(void* arg) { |
|
|
|
break; |
|
|
|
|
|
|
|
/* Watch fd using select(2) */ |
|
|
|
FD_ZERO(&sread); |
|
|
|
FD_ZERO(&swrite); |
|
|
|
memset(s->sread, 0, s->sread_sz); |
|
|
|
memset(s->swrite, 0, s->swrite_sz); |
|
|
|
|
|
|
|
if (uv_is_readable(stream)) |
|
|
|
FD_SET(fd, &sread); |
|
|
|
FD_SET(fd, s->sread); |
|
|
|
if (uv_is_writable(stream)) |
|
|
|
FD_SET(fd, &swrite); |
|
|
|
FD_SET(s->int_fd, &sread); |
|
|
|
FD_SET(fd, s->swrite); |
|
|
|
FD_SET(s->int_fd, s->sread); |
|
|
|
|
|
|
|
/* Wait indefinitely for fd events */ |
|
|
|
r = select(max_fd + 1, &sread, &swrite, NULL, NULL); |
|
|
|
r = select(max_fd + 1, s->sread, s->swrite, NULL, NULL); |
|
|
|
if (r == -1) { |
|
|
|
if (errno == EINTR) |
|
|
|
continue; |
|
|
@ -177,7 +179,7 @@ static void uv__stream_osx_select(void* arg) { |
|
|
|
continue; |
|
|
|
|
|
|
|
/* Empty socketpair's buffer in case of interruption */ |
|
|
|
if (FD_ISSET(s->int_fd, &sread)) |
|
|
|
if (FD_ISSET(s->int_fd, s->sread)) |
|
|
|
while (1) { |
|
|
|
r = read(s->int_fd, buf, sizeof(buf)); |
|
|
|
|
|
|
@ -198,12 +200,12 @@ static void uv__stream_osx_select(void* arg) { |
|
|
|
|
|
|
|
/* Handle events */ |
|
|
|
events = 0; |
|
|
|
if (FD_ISSET(fd, &sread)) |
|
|
|
if (FD_ISSET(fd, s->sread)) |
|
|
|
events |= UV__POLLIN; |
|
|
|
if (FD_ISSET(fd, &swrite)) |
|
|
|
if (FD_ISSET(fd, s->swrite)) |
|
|
|
events |= UV__POLLOUT; |
|
|
|
|
|
|
|
assert(events != 0 || FD_ISSET(s->int_fd, &sread)); |
|
|
|
assert(events != 0 || FD_ISSET(s->int_fd, s->sread)); |
|
|
|
if (events != 0) { |
|
|
|
ACCESS_ONCE(int, s->events) = events; |
|
|
|
|
|
|
@ -283,6 +285,10 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) { |
|
|
|
int ret; |
|
|
|
int kq; |
|
|
|
int old_fd; |
|
|
|
int max_fd; |
|
|
|
size_t sread_sz; |
|
|
|
size_t swrite_sz; |
|
|
|
int err; |
|
|
|
|
|
|
|
kq = kqueue(); |
|
|
|
if (kq == -1) { |
|
|
@ -306,30 +312,52 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) { |
|
|
|
return 0; |
|
|
|
|
|
|
|
/* At this point we definitely know that this fd won't work with kqueue */ |
|
|
|
s = malloc(sizeof(*s)); |
|
|
|
if (s == NULL) |
|
|
|
return uv__set_artificial_error(stream->loop, UV_ENOMEM); |
|
|
|
|
|
|
|
/*
|
|
|
|
* Create fds for io watcher and to interrupt the select() loop. |
|
|
|
* NOTE: do it ahead of malloc below to allocate enough space for fd_sets |
|
|
|
*/ |
|
|
|
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds)) |
|
|
|
return uv__set_sys_error(stream->loop, errno); |
|
|
|
|
|
|
|
max_fd = *fd; |
|
|
|
if (fds[1] > max_fd) |
|
|
|
max_fd = fds[1]; |
|
|
|
|
|
|
|
sread_sz = (max_fd + NBBY) / NBBY; |
|
|
|
swrite_sz = sread_sz; |
|
|
|
|
|
|
|
s = malloc(sizeof(*s) + sread_sz + swrite_sz); |
|
|
|
if (s == NULL) { |
|
|
|
err = uv__set_artificial_error(stream->loop, UV_ENOMEM); |
|
|
|
goto failed_malloc; |
|
|
|
} |
|
|
|
|
|
|
|
s->events = 0; |
|
|
|
s->fd = *fd; |
|
|
|
s->sread = (fd_set*) ((char*) s + sizeof(*s)); |
|
|
|
s->sread_sz = sread_sz; |
|
|
|
s->swrite = (fd_set*) ((char*) s->sread + sread_sz); |
|
|
|
s->swrite_sz = swrite_sz; |
|
|
|
|
|
|
|
if (uv_async_init(stream->loop, &s->async, uv__stream_osx_select_cb)) { |
|
|
|
SAVE_ERRNO(free(s)); |
|
|
|
return uv__set_sys_error(stream->loop, errno); |
|
|
|
} |
|
|
|
err = uv_async_init(stream->loop, &s->async, uv__stream_osx_select_cb); |
|
|
|
if (err) |
|
|
|
goto failed_async_init; |
|
|
|
|
|
|
|
s->async.flags |= UV__HANDLE_INTERNAL; |
|
|
|
uv__handle_unref(&s->async); |
|
|
|
|
|
|
|
if (uv_sem_init(&s->close_sem, 0)) |
|
|
|
goto fatal1; |
|
|
|
|
|
|
|
if (uv_sem_init(&s->async_sem, 0)) |
|
|
|
goto fatal2; |
|
|
|
err = uv_sem_init(&s->close_sem, 0); |
|
|
|
if (err != 0) { |
|
|
|
err = uv__set_sys_error(stream->loop, UV_UNKNOWN); |
|
|
|
goto failed_close_sem_init; |
|
|
|
} |
|
|
|
|
|
|
|
/* Create fds for io watcher and to interrupt the select() loop. */ |
|
|
|
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds)) |
|
|
|
goto fatal3; |
|
|
|
err = uv_sem_init(&s->async_sem, 0); |
|
|
|
if (err != 0) { |
|
|
|
err = uv__set_sys_error(stream->loop, UV_UNKNOWN); |
|
|
|
goto failed_async_sem_init; |
|
|
|
} |
|
|
|
|
|
|
|
s->fake_fd = fds[0]; |
|
|
|
s->int_fd = fds[1]; |
|
|
@ -339,26 +367,37 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) { |
|
|
|
stream->select = s; |
|
|
|
*fd = s->fake_fd; |
|
|
|
|
|
|
|
if (uv_thread_create(&s->thread, uv__stream_osx_select, stream)) |
|
|
|
goto fatal4; |
|
|
|
err = uv_thread_create(&s->thread, uv__stream_osx_select, stream); |
|
|
|
if (err != 0) { |
|
|
|
err = uv__set_sys_error(stream->loop, UV_UNKNOWN); |
|
|
|
goto failed_thread_create; |
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
fatal4: |
|
|
|
failed_thread_create: |
|
|
|
s->stream = NULL; |
|
|
|
stream->select = NULL; |
|
|
|
*fd = old_fd; |
|
|
|
close(s->fake_fd); |
|
|
|
close(s->int_fd); |
|
|
|
s->fake_fd = -1; |
|
|
|
s->int_fd = -1; |
|
|
|
fatal3: |
|
|
|
uv_sem_destroy(&s->async_sem); |
|
|
|
fatal2: |
|
|
|
|
|
|
|
failed_async_sem_init: |
|
|
|
uv_sem_destroy(&s->close_sem); |
|
|
|
fatal1: |
|
|
|
|
|
|
|
failed_close_sem_init: |
|
|
|
close(fds[0]); |
|
|
|
close(fds[1]); |
|
|
|
uv_close((uv_handle_t*) &s->async, uv__stream_osx_cb_close); |
|
|
|
return uv__set_sys_error(stream->loop, errno); |
|
|
|
return err; |
|
|
|
|
|
|
|
failed_async_init: |
|
|
|
free(s); |
|
|
|
|
|
|
|
failed_malloc: |
|
|
|
close(fds[0]); |
|
|
|
close(fds[1]); |
|
|
|
|
|
|
|
return err; |
|
|
|
} |
|
|
|
#endif /* defined(__APPLE__) */ |
|
|
|
|
|
|
|