diff options
author | usa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2008-07-15 12:34:58 +0000 |
---|---|---|
committer | usa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2008-07-15 12:34:58 +0000 |
commit | c9eba6932be3ad3e43bb002ca1c4e2375e5b6d1c (patch) | |
tree | eb12f42458966d9fe163d670e3d81fb6b63114fe /ext | |
parent | 6bc480e059b0b9a6a24dceaa96e2d0717cceca51 (diff) | |
download | ruby-c9eba6932be3ad3e43bb002ca1c4e2375e5b6d1c.tar.gz |
* ext/socket/socket.c (ruby_connect, s_accept): came back blocking
region because other thread/process maybe read/write the socket
between select() and connect()/accept().
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@18073 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext')
-rw-r--r-- | ext/socket/socket.c | 35 |
1 files changed, 27 insertions, 8 deletions
diff --git a/ext/socket/socket.c b/ext/socket/socket.c index 910a1ab559..14ed6fe963 100644 --- a/ext/socket/socket.c +++ b/ext/socket/socket.c @@ -1142,16 +1142,18 @@ struct connect_arg { socklen_t len; }; -static int -connect0(struct connect_arg *arg) +static VALUE +connect_blocking(void *data) { + struct connect_arg *arg = data; return connect(arg->fd, arg->sockaddr, arg->len); } #if defined(SOCKS) && !defined(SOCKS5) -static int -socks_connect0(struct connect_arg *arg) +static VALUE +socks_connect_blocking(void *data) { + struct connect_arg *arg = data; return Rconnect(arg->fd, arg->sockaddr, arg->len); } #endif @@ -1160,7 +1162,7 @@ static int ruby_connect(int fd, const struct sockaddr *sockaddr, int len, int socks) { int status; - int (*func)(struct connect_arg *) = connect0; + rb_blocking_function_t *func = connect_blocking; struct connect_arg arg; #if WAIT_IN_PROGRESS > 0 int wait_in_progress = -1; @@ -1172,11 +1174,11 @@ ruby_connect(int fd, const struct sockaddr *sockaddr, int len, int socks) arg.sockaddr = sockaddr; arg.len = len; #if defined(SOCKS) && !defined(SOCKS5) - if (socks) func = socks_connect0; + if (socks) func = socks_connect_blocking; #endif for (;;) { rb_thread_fd_writable(fd); - status = func(&arg); + status = BLOCKING_REGION(func, &arg); if (status < 0) { switch (errno) { case EAGAIN: @@ -1526,16 +1528,33 @@ s_accept_nonblock(VALUE klass, rb_io_t *fptr, struct sockaddr *sockaddr, socklen return init_sock(rb_obj_alloc(klass), fd2); } +struct accept_arg { + int fd; + struct sockaddr *sockaddr; + socklen_t *len; +}; + +static VALUE +accept_blocking(void *data) +{ + struct accept_arg *arg = data; + return (VALUE)accept(arg->fd, arg->sockaddr, arg->len); +} + static VALUE s_accept(VALUE klass, int fd, struct sockaddr *sockaddr, socklen_t *len) { int fd2; int retry = 0; + struct accept_arg arg; rb_secure(3); + arg.fd = fd; + arg.sockaddr = sockaddr; + arg.len = len; retry: rb_thread_wait_fd(fd); - fd2 = accept(fd, sockaddr, len); + fd2 = BLOCKING_REGION(accept_blocking, &arg); if (fd2 < 0) { switch (errno) { case EMFILE: |