[前][次][番号順一覧][スレッド一覧]

ruby-changes:12867

From: wyhaines <ko1@a...>
Date: Fri, 21 Aug 2009 02:22:17 +0900 (JST)
Subject: [ruby-changes:12867] Ruby:r24600 (ruby_1_8_6): Backport #1001; handle EBADF in select() to avoid Interpreter-wide deadlock when native close() is called on fd which is currently being IO#select()ed.

wyhaines	2009-08-21 02:22:00 +0900 (Fri, 21 Aug 2009)

  New Revision: 24600

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=24600

  Log:
    Backport #1001; handle EBADF in select() to avoid Interpreter-wide deadlock when native close() is called on fd which is currently being IO#select()ed.

  Modified files:
    branches/ruby_1_8_6/ChangeLog
    branches/ruby_1_8_6/eval.c
    branches/ruby_1_8_6/version.h

Index: ruby_1_8_6/ChangeLog
===================================================================
--- ruby_1_8_6/ChangeLog	(revision 24599)
+++ ruby_1_8_6/ChangeLog	(revision 24600)
@@ -1,6 +1,10 @@
+Thu Augh 20 9:43:00 2009 Kirk Haines <khaines@r...>
+
+	* Backport #1001; Handle EBADF to fix problem with interpreter wide deadlock when native close() is called on fd which is currently being IO#select()ed.
+
 Wed Aug 19 1:49:00 2009 Kirk Haines <khaines@r...>
 
-	* Backport #1232; Writes one extra byte to the buffer in order to prevent overrun.
+	* Backport #1232; Writes one extra byte to the buffer in order to prevent overrun. r24583
 
 Tue Aug 4   8:53:00 2009 Kirk Haines <khaines@r...>
 
Index: ruby_1_8_6/version.h
===================================================================
--- ruby_1_8_6/version.h	(revision 24599)
+++ ruby_1_8_6/version.h	(revision 24600)
@@ -1,15 +1,15 @@
 #define RUBY_VERSION "1.8.6"
-#define RUBY_RELEASE_DATE "2009-08-19"
+#define RUBY_RELEASE_DATE "2009-08-20"
 #define RUBY_VERSION_CODE 186
-#define RUBY_RELEASE_CODE 20090819
-#define RUBY_PATCHLEVEL 384
+#define RUBY_RELEASE_CODE 20090820
+#define RUBY_PATCHLEVEL 386
 
 #define RUBY_VERSION_MAJOR 1
 #define RUBY_VERSION_MINOR 8
 #define RUBY_VERSION_TEENY 6
 #define RUBY_RELEASE_YEAR 2009
 #define RUBY_RELEASE_MONTH 8
-#define RUBY_RELEASE_DAY 19
+#define RUBY_RELEASE_DAY 20
 
 #ifdef RUBY_EXTERN
 RUBY_EXTERN const char ruby_version[];
Index: ruby_1_8_6/eval.c
===================================================================
--- ruby_1_8_6/eval.c	(revision 24599)
+++ ruby_1_8_6/eval.c	(revision 24600)
@@ -74,7 +74,16 @@
 
 #include <time.h>
 
-#ifdef __BEOS__
+#if defined(HAVE_FCNTL_H) || defined(_WIN32)
+#include <fcntl.h>
+#elif defined(HAVE_SYS_FCNTL_H)
+#include <sys/fcntl.h>
+#endif
+#ifdef __CYGWIN__
+#include <io.h>
+#endif
+
+#if defined(__BEOS__) && !defined(BONE)
 #include <net/socket.h>
 #endif
 
@@ -10801,20 +10810,60 @@
 #ifdef ERESTART
 	    if (e == ERESTART) goto again;
 #endif
-	    FOREACH_THREAD_FROM(curr, th) {
-		if (th->wait_for & WAIT_SELECT) {
-		    int v = 0;
+            if (e == EBADF) {
+                int badfd = -1;
+                int fd;
+                int dummy;
+                for (fd = 0; fd <= max; fd++) {
+                    if ((FD_ISSET(fd, &readfds) ||
+                         FD_ISSET(fd, &writefds) ||
+                         FD_ISSET(fd, &exceptfds)) &&
+                        fcntl(fd, F_GETFD, &dummy) == -1 &&
+                        errno == EBADF) {
+                        badfd = fd;
+                        break;
+                    }
+                }
+                if (badfd != -1) {
+                    FOREACH_THREAD_FROM(curr, th) {
+                        if (th->wait_for & WAIT_FD) {
+                            if (th->fd == badfd) {
+                                found = 1;
+                                th->status = THREAD_RUNNABLE;
+                                th->fd = 0;
+                                break;
+                            }
+                        }
+                        if (th->wait_for & WAIT_SELECT) {
+                            if (FD_ISSET(badfd, &th->readfds) ||
+                                FD_ISSET(badfd, &th->writefds) ||
+                                FD_ISSET(badfd, &th->exceptfds)) {
+                                found = 1;
+                                th->status = THREAD_RUNNABLE;
+                                th->select_value = -EBADF;
+                                break;
+                            }
+                        }
+                    }
+                    END_FOREACH_FROM(curr, th);
+                }
+            }
+            else {
+                FOREACH_THREAD_FROM(curr, th) {
+                    if (th->wait_for & WAIT_SELECT) {
+                        int v = 0;
 
-		    v |= find_bad_fds(&readfds, &th->readfds, th->fd);
-		    v |= find_bad_fds(&writefds, &th->writefds, th->fd);
-		    v |= find_bad_fds(&exceptfds, &th->exceptfds, th->fd);
-		    if (v) {
-			th->select_value = n;
-			n = max;
-		    }
-		}
-	    }
-	    END_FOREACH_FROM(curr, th);
+                        v |= find_bad_fds(&readfds, &th->readfds, th->fd);
+                        v |= find_bad_fds(&writefds, &th->writefds, th->fd);
+                        v |= find_bad_fds(&exceptfds, &th->exceptfds, th->fd);
+                        if (v) {
+                            th->select_value = n;
+                            n = max;
+                        }
+                    }
+                }
+                END_FOREACH_FROM(curr, th);
+            }
 	}
  	if (select_timeout && n == 0) {
  	    if (now < 0.0) now = timeofday();
@@ -11125,6 +11174,10 @@
     if (read) *read = curr_thread->readfds;
     if (write) *write = curr_thread->writefds;
     if (except) *except = curr_thread->exceptfds;
+    if (curr_thread->select_value < 0) {
+        errno = -curr_thread->select_value;
+        return -1;
+    }
     return curr_thread->select_value;
 }
 

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]