static VALUE my_connect(VALUE klass, int io_wait, int domain, void *addr, socklen_t addrlen) { int fd = socket(domain, MY_SOCK_STREAM, 0); if (fd == -1) { switch (errno) { case EMFILE: case ENFILE: #ifdef ENOBUFS case ENOBUFS: #endif /* ENOBUFS */ errno = 0; rb_gc(); fd = socket(domain, MY_SOCK_STREAM, 0); } if (fd == -1) rb_sys_fail("socket"); } #ifndef SOCK_NONBLOCK if (fcntl(fd, F_SETFL, O_RDWR | O_NONBLOCK) == -1) close_fail(fd, "fcntl(F_SETFL, O_RDWR | O_NONBLOCK)"); #endif /* SOCK_NONBLOCK */ if (connect(fd, addr, addrlen) == -1) { if (errno == EINPROGRESS) { VALUE io = sock_for_fd(klass, fd); if (io_wait) { errno = EAGAIN; (void)kgio_call_wait_writable(io); } return io; } close_fail(fd, "connect"); } return sock_for_fd(klass, fd); }
static VALUE my_connect(VALUE klass, int io_wait, int domain, const void *addr, socklen_t addrlen) { int fd = my_socket(domain); if (connect(fd, addr, addrlen) < 0) { if (errno == EINPROGRESS) { VALUE io = sock_for_fd(klass, fd); if (io_wait) { errno = EAGAIN; (void)kgio_call_wait_writable(io); } return io; } close_fail(fd, "connect"); } return sock_for_fd(klass, fd); }
/* try to use SOCK_NONBLOCK and SOCK_CLOEXEC */ static int my_socket(int domain) { int fd; retry: fd = socket(domain, MY_SOCK_STREAM, 0); if (fd < 0) { switch (errno) { case EMFILE: case ENFILE: #ifdef ENOBUFS case ENOBUFS: #endif /* ENOBUFS */ errno = 0; rb_gc(); fd = socket(domain, MY_SOCK_STREAM, 0); break; case EINVAL: if (MY_SOCK_STREAM != SOCK_STREAM) { MY_SOCK_STREAM = SOCK_STREAM; goto retry; } } if (fd < 0) rb_sys_fail("socket"); } if (MY_SOCK_STREAM == SOCK_STREAM) { if (fcntl(fd, F_SETFL, O_RDWR | O_NONBLOCK) < 0) close_fail(fd, "fcntl(F_SETFL, O_RDWR | O_NONBLOCK)"); rb_fd_fix_cloexec(fd); } return fd; }