summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorusa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-07-15 12:34:58 +0000
committerusa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-07-15 12:34:58 +0000
commitc9eba6932be3ad3e43bb002ca1c4e2375e5b6d1c (patch)
treeeb12f42458966d9fe163d670e3d81fb6b63114fe /ext
parent6bc480e059b0b9a6a24dceaa96e2d0717cceca51 (diff)
* 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.c35
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: