From: Sylvain Joyeux Date: 2007-03-15T00:15:57+09:00 Subject: [PATCH] grave bug in 1.8.6's thread implementation --Boundary-00=_fGB+Fbf4w7F52qz Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline In ext/thread/thread.c, remove_one leaves the list in an inconsistent state. The fix is in thread-mutex-remove_one.diff. Is it me or there is no testsuite for multithread-related stuff ? That's a pity, fastthread did include one :-( Other patches: thread-mutex-not_owner.diff makes lock_mutex check that the mutex is actually owned by the caller. thread-mutex-recursive_lock.diff raises if we are trying to recursively lock the mutex. (Note that I can as easily add a recursive mutex behaviour) Best regards Sylvain Joyeux --Boundary-00=_fGB+Fbf4w7F52qz Content-Type: text/x-diff; charset="us-ascii"; name="thread-mutex-not_owner.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="thread-mutex-not_owner.diff" --- /home/sjoyeux/system/ruby-1.8.6/ext/thread/thread.c 2007-03-03 11:08:06.000000000 +0100 +++ thread.c 2007-03-14 15:36:58.000000000 +0100 @@ -429,8 +443,13 @@ unlock_mutex_inner(Mutex *mutex) VALUE waking; if (!RTEST(mutex->owner)) { - return Qundef; + rb_raise(rb_eThreadError, "not owner"); + } + + if (mutex->owner != rb_thread_current()) { + rb_raise(rb_eThreadError, "not owner"); } + mutex->owner = Qnil; waking = wake_one(&mutex->waiting); --Boundary-00=_fGB+Fbf4w7F52qz Content-Type: text/x-diff; charset="us-ascii"; name="thread-mutex-recursive_lock.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="thread-mutex-recursive_lock.diff" --- /home/sjoyeux/system/ruby-1.8.6/ext/thread/thread.c 2007-03-03 11:08:06.000000000 +0100 +++ thread.c 2007-03-14 15:45:24.000000000 +0100 @@ -399,6 +410,9 @@ lock_mutex(Mutex *mutex) rb_thread_critical = 1; while (RTEST(mutex->owner)) { + if (mutex->owner == current) + rb_raise(rb_eThreadError, "recursive mutex lock"); + wait_list(&mutex->waiting); rb_thread_critical = 1; } --Boundary-00=_fGB+Fbf4w7F52qz Content-Type: text/x-diff; charset="us-ascii"; name="thread-mutex-remove_one.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="thread-mutex-remove_one.diff" --- /home/sjoyeux/system/ruby-1.8.6/ext/thread/thread.c 2007-03-03 11:08:06.000000000 +0100 +++ thread.c 2007-03-14 15:36:58.000000000 +0100 @@ -429,8 +433,13 @@ unlock_mutex_inner(Mutex *mutex) VALUE waking; if (!RTEST(mutex->owner)) { - return Qundef; + rb_raise(rb_eThreadError, "Not owner"); } + + if (mutex->owner != rb_thread_current()) { + rb_raise(rb_eThreadError, "Not owner"); + } + mutex->owner = Qnil; waking = wake_one(&mutex->waiting); --Boundary-00=_fGB+Fbf4w7F52qz--