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

ruby-changes:14592

From: wyhaines <ko1@a...>
Date: Wed, 27 Jan 2010 03:06:56 +0900 (JST)
Subject: [ruby-changes:14592] Ruby:r26435 (ruby_1_8_6): Backport #2039 ; backported r24413, r24416, r24442 to fix a problem with IO#select and threads. This is the same issue as Bug #199

wyhaines	2010-01-27 03:06:41 +0900 (Wed, 27 Jan 2010)

  New Revision: 26435

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

  Log:
    Backport #2039 [ruby-core:25339]; backported r24413, r24416, r24442 to fix a problem with IO#select and threads. This is the same issue as Bug #199
    3 [ruby-core:25114].

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

Index: ruby_1_8_6/ChangeLog
===================================================================
--- ruby_1_8_6/ChangeLog	(revision 26434)
+++ ruby_1_8_6/ChangeLog	(revision 26435)
@@ -1,8 +1,12 @@
+Tue Jan 26 3:03:00 2010 Kirk Haines <khaines@r...>
+
+	* eval.c: Backport #2039 [ruby-core:25339]; backported r24413, r24416, r24442 to fix a problem with IO#select and threads. This is the same issues as Bug #1993 [ruby-core:25114].
+
 Thu Jan 21 5:10:00 2010 Kirk Haines <khaines@r...>
 
-	* eval.c: Backport #2592 [ruby-core:27525]; Added an ifndef for WIN32 so that F_GETFD isn't used on that platform. Fixes a build issue.
+	* eval.c: Backport #2592 [ruby-core:27525]; Added an ifndef for WIN32 so that F_GETFD isn't used on that platform. Fixes a build issue. r26361
 
-	* dln.c: Bug #2220 [ruby-core:26117]; Patch to fix dln.c so that extensions work properly under Snow Leopard.
+	* dln.c: Bug #2220 [ruby-core:26117]; Patch to fix dln.c so that extensions work properly under Snow Leopard. 26361
 
 Sun Jan 10 8:00:00 2010  Kirk Haines  <khaines@r...>
 
Index: ruby_1_8_6/eval.c
===================================================================
--- ruby_1_8_6/eval.c	(revision 26434)
+++ ruby_1_8_6/eval.c	(revision 26435)
@@ -9913,6 +9913,7 @@
 #define WAIT_TIME	(1<<2)
 #define WAIT_JOIN	(1<<3)
 #define WAIT_PID	(1<<4)
+#define WAIT_DONE	(1<<5)
 
 /* +infty, for this purpose */
 #define DELAY_INFTY 1E30
@@ -10737,6 +10738,7 @@
     now = -1.0;
 
     FOREACH_THREAD_FROM(curr, th) {
+        th->wait_for &= ~WAIT_DONE;
 	if (!found && th->status <= THREAD_RUNNABLE) {
 	    found = 1;
 	}
@@ -10769,7 +10771,12 @@
 	    if (now < 0.0) now = timeofday();
 	    th_delay = th->delay - now;
 	    if (th_delay <= 0.0) {
-		th->status = THREAD_RUNNABLE;
+                if (th->wait_for & WAIT_SELECT) {
+                    need_select = 1;
+                }
+                else {
+                    th->status = THREAD_RUNNABLE;
+                } 
 		found = 1;
 	    }
 	    else if (th_delay < delay) {
@@ -10888,22 +10895,22 @@
 	if (n > 0) {
 	    now = -1.0;
 	    /* Some descriptors are ready.
-             * Choose a thread which may run next.
-             * Don't change the status of threads which don't run next.
+             * The corresponding threads are runnable as next.
+             * Mark them with WAIT_DONE.
+             * Don't change the status to runnable here because
+             * threads which don't run next should not be changed. 
              */
 	    FOREACH_THREAD_FROM(curr, th) {
 		if ((th->wait_for&WAIT_FD) && FD_ISSET(th->fd, &readfds)) {
-                    th_found = th;
+                    th->wait_for |= WAIT_DONE; 
 		    found = 1;
-                    break;
 		}
 		if ((th->wait_for&WAIT_SELECT) &&
 		    (match_fds(&readfds, &th->readfds, max) ||
 		     match_fds(&writefds, &th->writefds, max) ||
 		     match_fds(&exceptfds, &th->exceptfds, max))) {
-                    th_found = th;
+                    th->wait_for |= WAIT_DONE;
                     found = 1;
-                    break;
 		}
 	    }
 	    END_FOREACH_FROM(curr, th);
@@ -10915,31 +10922,32 @@
     }
 
     FOREACH_THREAD_FROM(curr, th) {
-	if (th->status == THREAD_TO_KILL) {
-	    next = th;
-	    break;
-	}
-	if ((th->status == THREAD_RUNNABLE || th == th_found) && th->stk_ptr) {
-	    if (!next || next->priority < th->priority) {
-                if (th == th_found) {
-                    th_found->status = THREAD_RUNNABLE;
-                    th_found->wait_for = 0;
-                    if (th->wait_for&WAIT_FD) {
-                        th_found->fd = 0;
-                    }
-                    else { /* th->wait_for&WAIT_SELECT */
-                        n = intersect_fds(&readfds, &th_found->readfds, max) +
-                            intersect_fds(&writefds, &th_found->writefds, max) +
-                            intersect_fds(&exceptfds, &th_found->exceptfds, max);
-                        th_found->select_value = n;
-                    }
-                }
-	        next = th;
+        if (th->status == THREAD_TO_KILL) {
+            next = th;
+            break;
+        }
+        if ((th->status == THREAD_RUNNABLE || (th->wait_for & WAIT_DONE)) && th->stk_ptr) {
+            if (!next || next->priority < th->priority) {
+                next = th;
             }
-	}
+        }
     }
     END_FOREACH_FROM(curr, th);
 
+    if (next && (next->wait_for & WAIT_DONE)) {
+        next->status = THREAD_RUNNABLE;
+        if (next->wait_for&WAIT_FD) {
+            next->fd = 0;
+        }
+        else { /* next->wait_for&WAIT_SELECT */
+            n = intersect_fds(&readfds, &next->readfds, max) +
+                intersect_fds(&writefds, &next->writefds, max) +
+                intersect_fds(&exceptfds, &next->exceptfds, max);
+            next->select_value = n;
+        }
+        next->wait_for = 0;
+    }
+
     if (!next) {
 	/* raise fatal error to main thread */
 	curr_thread->node = ruby_current_node;
@@ -10949,15 +10957,16 @@
 	    TRAP_END;
 	}
 	FOREACH_THREAD_FROM(curr, th) {
+            int wait_for = th->wait_for & ~WAIT_DONE; 
 	    warn_printf("deadlock 0x%lx: %s:",
 			th->thread, thread_status_name(th->status));
-	    if (th->wait_for & WAIT_FD) warn_printf("F(%d)", th->fd);
-	    if (th->wait_for & WAIT_SELECT) warn_printf("S");
-	    if (th->wait_for & WAIT_TIME) warn_printf("T(%f)", th->delay);
-	    if (th->wait_for & WAIT_JOIN)
+            if (wait_for & WAIT_FD) warn_printf("F(%d)", th->fd);
+            if (wait_for & WAIT_SELECT) warn_printf("S");
+            if (wait_for & WAIT_TIME) warn_printf("T(%f)", th->delay);
+            if (wait_for & WAIT_JOIN)
 		warn_printf("J(0x%lx)", th->join ? th->join->thread : 0);
-	    if (th->wait_for & WAIT_PID) warn_printf("P");
-	    if (!th->wait_for) warn_printf("-");
+            if (wait_for & WAIT_PID) warn_printf("P");
+            if (!wait_for) warn_printf("-");
 	    warn_printf(" %s - %s:%d\n",
 			th==main_thread ? "(main)" : "",
 			th->node->nd_file, nd_line(th->node));

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

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