int uv__make_pipe(int fds[2], int flags) { #if __linux__ int fl; fl = UV__O_CLOEXEC; if (flags & UV__F_NONBLOCK) fl |= UV__O_NONBLOCK; if (uv__pipe2(fds, fl) == 0) return 0; if (errno != ENOSYS) return -1; #endif if (pipe(fds)) return -1; uv__cloexec(fds[0], 1); uv__cloexec(fds[1], 1); if (flags & UV__F_NONBLOCK) { uv__nonblock(fds[0], 1); uv__nonblock(fds[1], 1); } return 0; }
static int uv__make_pipe(int fds[2], int flags) { #if HAVE_SYS_PIPE2 int fl; fl = O_CLOEXEC; if (flags & UV__F_NONBLOCK) fl |= O_NONBLOCK; if (sys_pipe2(fds, fl) == 0) return 0; if (errno != ENOSYS) return -1; /* errno == ENOSYS so maybe the kernel headers lied about * the availability of pipe2(). This can happen if people * build libuv against newer kernel headers than the kernel * they actually run the software on. */ #endif if (pipe(fds)) return -1; uv__cloexec(fds[0], 1); uv__cloexec(fds[1], 1); if (flags & UV__F_NONBLOCK) { uv__nonblock(fds[0], 1); uv__nonblock(fds[1], 1); } return 0; }
int uv__make_pipe(int fds[2], int flags) { #if defined(__linux__) static int no_pipe2; if (no_pipe2) goto skip; if (uv__pipe2(fds, flags | UV__O_CLOEXEC) == 0) return 0; if (errno != ENOSYS) return -errno; no_pipe2 = 1; skip: #endif if (pipe(fds)) return -errno; uv__cloexec(fds[0], 1); uv__cloexec(fds[1], 1); if (flags & UV__F_NONBLOCK) { uv__nonblock(fds[0], 1); uv__nonblock(fds[1], 1); } return 0; }
static int uv__make_socketpair(int fds[2], int flags) { #ifdef SOCK_NONBLOCK int fl; fl = SOCK_CLOEXEC; if (flags & UV__F_NONBLOCK) fl |= SOCK_NONBLOCK; if (socketpair(AF_UNIX, SOCK_STREAM|fl, 0, fds) == 0) return 0; if (errno != EINVAL) return -1; /* errno == EINVAL so maybe the kernel headers lied about * the availability of SOCK_NONBLOCK. This can happen if people * build libuv against newer kernel headers than the kernel * they actually run the software on. */ #endif if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds)) return -1; uv__cloexec(fds[0], 1); uv__cloexec(fds[1], 1); if (flags & UV__F_NONBLOCK) { uv__nonblock(fds[0], 1); uv__nonblock(fds[1], 1); } return 0; }
int uv__make_socketpair(int fds[2], int flags) { #if defined(__linux__) static int no_cloexec; if (no_cloexec) goto skip; if (socketpair(AF_UNIX, SOCK_STREAM | UV__SOCK_CLOEXEC | flags, 0, fds) == 0) return 0; /* Retry on EINVAL, it means SOCK_CLOEXEC is not supported. * Anything else is a genuine error. */ if (errno != EINVAL) return -errno; no_cloexec = 1; skip: #endif if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds)) return -errno; uv__cloexec(fds[0], 1); uv__cloexec(fds[1], 1); if (flags & UV__F_NONBLOCK) { uv__nonblock(fds[0], 1); uv__nonblock(fds[1], 1); } return 0; }
/* Open a socket in non-blocking close-on-exec mode, atomically if possible. */ int uv__socket(int domain, int type, int protocol) { int sockfd; #if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) sockfd = socket(domain, type | SOCK_NONBLOCK | SOCK_CLOEXEC, protocol); if (sockfd != -1) goto out; if (errno != EINVAL) goto out; #endif sockfd = socket(domain, type, protocol); if (sockfd == -1) goto out; if (uv__nonblock(sockfd, 1) || uv__cloexec(sockfd, 1)) { close(sockfd); sockfd = -1; } #if defined(SO_NOSIGPIPE) { int on = 1; setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof(on)); } #endif out: return sockfd; }
static int uv__process_open_stream(uv_stdio_container_t* container, int pipefds[2], int writable) { int flags; if (!(container->flags & UV_CREATE_PIPE) || pipefds[0] < 0) return 0; if (uv__close(pipefds[1])) if (errno != EINTR && errno != EINPROGRESS) abort(); pipefds[1] = -1; uv__nonblock(pipefds[0], 1); if (container->data.stream->type == UV_NAMED_PIPE && ((uv_pipe_t*)container->data.stream)->ipc) flags = UV_STREAM_READABLE | UV_STREAM_WRITABLE; else if (writable) flags = UV_STREAM_WRITABLE; else flags = UV_STREAM_READABLE; return uv__stream_open(container->data.stream, pipefds[0], flags); }
int uv_pipe_open(uv_pipe_t* handle, uv_os_fd_t fd) { int flags; int mode; int err; flags = 0; if (uv__fd_exists(handle->loop, fd)) return UV_EEXIST; do mode = fcntl(fd, F_GETFL); while (mode == -1 && errno == EINTR); if (mode == -1) return UV__ERR(errno); /* according to docs, must be EBADF */ err = uv__nonblock(fd, 1); if (err) return err; #if defined(__APPLE__) err = uv__stream_try_select((uv_stream_t*) handle, &fd); if (err) return err; #endif /* defined(__APPLE__) */ mode &= O_ACCMODE; if (mode != O_WRONLY) flags |= UV_HANDLE_READABLE; if (mode != O_RDONLY) flags |= UV_HANDLE_WRITABLE; return uv__stream_open((uv_stream_t*)handle, fd, flags); }
static int new_inotify_fd(void) { int err; int fd; fd = uv__inotify_init1(UV__IN_NONBLOCK | UV__IN_CLOEXEC); if (fd != -1) return fd; if (errno != ENOSYS) return -errno; fd = uv__inotify_init(); if (fd == -1) return -errno; err = uv__cloexec(fd, 1); if (err == 0) err = uv__nonblock(fd, 1); if (err) { uv__close(fd); return err; } return fd; }
/* Open a socket in non-blocking close-on-exec mode, atomically if possible. */ int uv__socket(int domain, int type, int protocol) { int sockfd; #if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) sockfd = socket(domain, type | SOCK_NONBLOCK | SOCK_CLOEXEC, protocol); if (sockfd != -1) goto out; if (errno != EINVAL) goto out; #endif sockfd = socket(domain, type, protocol); if (sockfd == -1) goto out; if (uv__nonblock(sockfd, 1) || uv__cloexec(sockfd, 1)) { uv__close(sockfd); sockfd = -1; } out: return sockfd; }
int uv_device_open(uv_loop_t* loop, uv_device_t* device, uv_os_fd_t fd, int flags) { int err; int stream_flags = 0; assert(device); if (flags != O_RDONLY && flags != O_WRONLY && flags != O_RDWR) { return -EINVAL; } uv__stream_init(loop, (uv_stream_t*) device, UV_DEVICE); if (flags & O_RDONLY) { stream_flags |= UV_STREAM_READABLE; } else if (flags & O_WRONLY) { stream_flags |= UV_STREAM_WRITABLE; } else if (flags & O_RDWR) { stream_flags |= UV_STREAM_READABLE | UV_STREAM_WRITABLE; } err = uv__nonblock(fd, 1); if (err) { return err; } err = uv__stream_open((uv_stream_t*) device, fd, stream_flags); if (err) { return err; } return 0; }
int uv__accept(int sockfd, struct sockaddr* saddr, socklen_t slen) { int peerfd; assert(sockfd >= 0); while (1) { #if __linux__ peerfd = uv__accept4(sockfd, saddr, &slen, UV__SOCK_NONBLOCK|UV__SOCK_CLOEXEC); if (peerfd != -1) break; if (errno == EINTR) continue; if (errno != ENOSYS) break; #endif if ((peerfd = accept(sockfd, saddr, &slen)) == -1) { if (errno == EINTR) continue; else break; } if (uv__cloexec(peerfd, 1) || uv__nonblock(peerfd, 1)) { close(peerfd); peerfd = -1; } break; } return peerfd; }
int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) { int err; if (uv__fd_exists(loop, fd)) return UV_EEXIST; err = uv__io_check_fd(loop, fd); if (err) return err; /* If ioctl(FIONBIO) reports ENOTTY, try fcntl(F_GETFL) + fcntl(F_SETFL). * Workaround for e.g. kqueue fds not supporting ioctls. */ err = uv__nonblock(fd, 1); if (err == UV_ENOTTY) if (uv__nonblock == uv__nonblock_ioctl) err = uv__nonblock_fcntl(fd, 1); if (err) return err; uv__handle_init(loop, (uv_handle_t*) handle, UV_POLL); uv__io_init(&handle->io_watcher, uv__poll_io, fd); handle->poll_cb = NULL; return 0; }
/* Open a socket in non-blocking close-on-exec mode, atomically if possible. */ int uv__socket(int domain, int type, int protocol) { int sockfd; int err; #if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) sockfd = socket(domain, type | SOCK_NONBLOCK | SOCK_CLOEXEC, protocol); if (sockfd != -1) return sockfd; if (errno != EINVAL) return -errno; #endif sockfd = socket(domain, type, protocol); if (sockfd == -1) return -errno; err = uv__nonblock(sockfd, 1); if (err == 0) err = uv__cloexec(sockfd, 1); if (err) { uv__close(sockfd); return err; } #if defined(SO_NOSIGPIPE) { int on = 1; setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof(on)); } #endif return sockfd; }
int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) { int err; err = uv__nonblock(sock, 1); if (err) return err; return uv__stream_open((uv_stream_t*)handle, sock, UV_STREAM_READABLE | UV_STREAM_WRITABLE); }
int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) { int err; err = uv__nonblock(fd, 1); if (err) return err; uv__handle_init(loop, (uv_handle_t*) handle, UV_POLL); uv__io_init(&handle->io_watcher, uv__poll_io, fd); handle->poll_cb = NULL; return 0; }
int uv__accept(int sockfd) { int peerfd; int err; assert(sockfd >= 0); while (1) { #if defined(__linux__) || \ (defined(__FreeBSD__) && __FreeBSD__ >= 10) || \ defined(__NetBSD__) static int no_accept4; if (no_accept4) goto skip; peerfd = uv__accept4(sockfd, NULL, NULL, UV__SOCK_NONBLOCK|UV__SOCK_CLOEXEC); if (peerfd != -1) return peerfd; if (errno == EINTR) continue; if (errno != ENOSYS) return UV__ERR(errno); no_accept4 = 1; skip: #endif peerfd = accept(sockfd, NULL, NULL); if (peerfd == -1) { if (errno == EINTR) continue; return UV__ERR(errno); } err = uv__cloexec(peerfd, 1); if (err == 0) err = uv__nonblock(peerfd, 1); if (err) { uv__close(peerfd); return err; } return peerfd; } }
int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { int flags; int newfd; int r; uv__stream_init(loop, (uv_stream_t*)tty, UV_TTY); /* Reopen the file descriptor when it refers to a tty. This lets us put the * tty in non-blocking mode without affecting other processes that share it * with us. * * Example: `node | cat` - if we put our fd 0 in non-blocking mode, it also * affects fd 1 of `cat` because both file descriptors refer to the same * struct file in the kernel. When we reopen our fd 0, it points to a * different struct file, hence changing its properties doesn't affect * other processes. */ if (isatty(fd)) { newfd = open("/dev/tty", O_RDWR); if (newfd == -1) return uv__set_sys_error(loop, errno); do r = dup2(newfd, fd); while (r == -1 && (errno == EINTR || errno == EBUSY)); /* EINVAL means newfd == fd which could conceivably happen if another * thread called close(fd) between our calls to isatty() and open(). * That's a rather unlikely event but let's handle it anyway. */ if (r == -1 && errno != EINVAL) { close(newfd); return uv__set_sys_error(loop, errno); } fd = newfd; } if (readable) flags = UV_STREAM_READABLE; else flags = UV_STREAM_WRITABLE; uv__nonblock(fd, 1); uv__stream_open((uv_stream_t*)tty, fd, flags); tty->mode = 0; return 0; }
int uv__accept(int sockfd) { int peerfd; int err; assert(sockfd >= 0); while (1) { #if defined(__linux__) static int no_accept4; no_accept4 = 1; /* accept4 doesn't work on QNAP */ if (no_accept4) goto skip; peerfd = uv__accept4(sockfd, NULL, NULL, UV__SOCK_NONBLOCK|UV__SOCK_CLOEXEC); if (peerfd != -1) return peerfd; if (errno == EINTR) continue; if (errno != ENOSYS) return -errno; no_accept4 = 1; skip: #endif peerfd = accept(sockfd, NULL, NULL); if (peerfd == -1) { if (errno == EINTR) continue; return -errno; } err = uv__cloexec(peerfd, 1); if (err == 0) err = uv__nonblock(peerfd, 1); if (err) { uv__close(peerfd); return err; } return peerfd; } }
int uv__accept(int sockfd) { int peerfd; assert(sockfd >= 0); while (1) { #if defined(__linux__) static int no_accept4; if (no_accept4) goto skip; peerfd = uv__accept4(sockfd, NULL, NULL, UV__SOCK_NONBLOCK|UV__SOCK_CLOEXEC); if (peerfd != -1) break; if (errno == EINTR) continue; if (errno != ENOSYS) break; no_accept4 = 1; skip: #endif peerfd = accept(sockfd, NULL, NULL); if (peerfd == -1) { if (errno == EINTR) continue; else break; } if (uv__cloexec(peerfd, 1) || uv__nonblock(peerfd, 1)) { close(peerfd); peerfd = -1; } break; } return peerfd; }
int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { uv__stream_init(loop, (uv_stream_t*)tty, UV_TTY); if (readable) { uv__nonblock(fd, 1); uv__stream_open((uv_stream_t*)tty, fd, UV_STREAM_READABLE); } else { /* Note: writable tty we set to blocking mode. */ uv__stream_open((uv_stream_t*)tty, fd, UV_STREAM_WRITABLE); tty->flags |= UV_STREAM_BLOCKING; } tty->mode = 0; return 0; }
int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { uv__stream_init(loop, (uv_stream_t*)tty, UV_TTY); if (readable) { uv__nonblock(fd, 1); uv__stream_open((uv_stream_t*)tty, fd, UV_READABLE); } else { /* Note: writable tty we set to blocking mode. */ uv__stream_open((uv_stream_t*)tty, fd, UV_WRITABLE); tty->blocking = 1; } loop->counters.tty_init++; tty->mode = 0; return 0; }
static int new_inotify_fd(void) { #if HAVE_INOTIFY_INIT1 return inotify_init1(IN_NONBLOCK | IN_CLOEXEC); #else int fd; if ((fd = inotify_init()) == -1) return -1; if (uv__cloexec(fd, 1) || uv__nonblock(fd, 1)) { SAVE_ERRNO(uv__close(fd)); fd = -1; } return fd; #endif }
int uv_pipe_open(uv_pipe_t* handle, uv_os_fd_t fd) { int err; err = uv__nonblock(fd, 1); if (err) return err; #if defined(__APPLE__) err = uv__stream_try_select((uv_stream_t*) handle, &fd); if (err) return err; #endif /* defined(__APPLE__) */ return uv__stream_open((uv_stream_t*)handle, fd, UV_STREAM_READABLE | UV_STREAM_WRITABLE); }
/* Open a socket in non-blocking close-on-exec mode, atomically if possible. */ int uv__socket(int domain, int type, int protocol) { #if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) return socket(domain, type | SOCK_NONBLOCK | SOCK_CLOEXEC, protocol); #else int sockfd; if ((sockfd = socket(domain, type, protocol)) == -1) { return -1; } if (uv__nonblock(sockfd, 1) == -1 || uv__cloexec(sockfd, 1) == -1) { uv__close(sockfd); return -1; } return sockfd; #endif }
int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) { int err; /* Check for already active socket. */ if (handle->io_watcher.fd != -1) return -EALREADY; /* FIXME(bnoordhuis) Should be -EBUSY. */ err = uv__nonblock(sock, 1); if (err) return err; err = uv__set_reuse(sock); if (err) return err; handle->io_watcher.fd = sock; return 0; }
int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) { int err; /* Check for already active socket. */ if (handle->io_watcher.fd != -1) return -EBUSY; err = uv__nonblock(sock, 1); if (err) return err; err = uv__set_reuse(sock); if (err) return err; handle->io_watcher.fd = sock; return 0; }
static int uv__process_open_stream(uv_stdio_container_t* container, int fds[2], int writable) { int fd = fds[writable ? 1 : 0]; int child_fd = fds[writable ? 0 : 1]; int flags; /* No need to create stream */ if (!(container->flags & UV_CREATE_PIPE) || fd < 0) { return 0; } assert(child_fd >= 0); close(child_fd); uv__nonblock(fd, 1); flags = uv__process_stdio_flags(container, writable); return uv__stream_open((uv_stream_t*)container->data.stream, fd, flags); }
static int new_inotify_fd(void) { int fd; fd = uv__inotify_init1(UV__IN_NONBLOCK | UV__IN_CLOEXEC); if (fd != -1) return fd; if (errno != ENOSYS) return -1; if ((fd = uv__inotify_init()) == -1) return -1; if (uv__cloexec(fd, 1) || uv__nonblock(fd, 1)) { SAVE_ERRNO(close(fd)); return -1; } return fd; }
int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { uv__stream_init(loop, (uv_stream_t*)tty, UV_TTY); #if defined(__APPLE__) if (uv__stream_try_select((uv_stream_t*) tty, &fd)) return -1; #endif /* defined(__APPLE__) */ if (readable) { uv__nonblock(fd, 1); uv__stream_open((uv_stream_t*)tty, fd, UV_STREAM_READABLE); } else { /* Note: writable tty we set to blocking mode. */ uv__stream_open((uv_stream_t*)tty, fd, UV_STREAM_WRITABLE); tty->flags |= UV_STREAM_BLOCKING; } tty->mode = 0; return 0; }