ext/kgio/connect.c in kgio-2.6.0 vs ext/kgio/connect.c in kgio-2.7.0
- old
+ new
@@ -7,40 +7,61 @@
(void)close(fd);
errno = saved_errno;
rb_sys_fail(msg);
}
-#ifdef SOCK_NONBLOCK
-# define MY_SOCK_STREAM (SOCK_STREAM|SOCK_NONBLOCK)
+static int MY_SOCK_STREAM =
+#if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC)
+# ifdef HAVE_RB_FD_FIX_CLOEXEC
+ (SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC)
+# else
+ (SOCK_STREAM|SOCK_NONBLOCK)
+# endif
#else
-# define MY_SOCK_STREAM SOCK_STREAM
+ SOCK_STREAM
#endif /* ! SOCK_NONBLOCK */
+;
+/* do not set close-on-exec by default on Ruby <2.0.0 */
+#ifndef HAVE_RB_FD_FIX_CLOEXEC
+# define rb_fd_fix_cloexec(fd) for (;0;)
+#endif /* HAVE_RB_FD_FIX_CLOEXEC */
+
static VALUE
my_connect(VALUE klass, int io_wait, int domain, void *addr, socklen_t addrlen)
{
- int fd = socket(domain, MY_SOCK_STREAM, 0);
+ int fd;
+retry:
+ 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);
+ break;
+ case EINVAL:
+ if (MY_SOCK_STREAM != SOCK_STREAM) {
+ MY_SOCK_STREAM = SOCK_STREAM;
+ goto retry;
+ }
}
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 (MY_SOCK_STREAM == SOCK_STREAM) {
+ if (fcntl(fd, F_SETFL, O_RDWR | O_NONBLOCK) == -1)
+ close_fail(fd, "fcntl(F_SETFL, O_RDWR | O_NONBLOCK)");
+ rb_fd_fix_cloexec(fd);
+ }
if (connect(fd, addr, addrlen) == -1) {
if (errno == EINPROGRESS) {
VALUE io = sock_for_fd(klass, fd);
@@ -61,10 +82,14 @@
struct sockaddr_storage addr;
int rc;
struct addrinfo *res;
const char *ipname = StringValuePtr(ip);
char ipport[6];
- unsigned uport = FIX2UINT(port);
+ unsigned uport;
+
+ if (TYPE(port) != T_FIXNUM)
+ rb_raise(rb_eTypeError, "port must be a non-negative integer");
+ uport = FIX2UINT(port);
rc = snprintf(ipport, sizeof(ipport), "%u", uport);
if (rc >= (int)sizeof(ipport) || rc <= 0)
rb_raise(rb_eArgError, "invalid TCP port: %u", uport);
memset(&hints, 0, sizeof(hints));