<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  <meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type">
  <title></title>
</head>
<body bgcolor="#ffffff" text="#000000">
Gonzalo Paniagua Javier wrote:
<blockquote cite="mid1095114207.5112.3.camel@localhost.localdomain"
 type="cite">
  <pre wrap="">On Mon, 2004-09-13 at 11:54, Scott Mohekey wrote:
  </pre>
  <blockquote type="cite">
    <pre wrap="">I've spent the last few days looking into the issue that has been 
reported here (<a class="moz-txt-link-freetext" href="http://bugs.ximian.com/show_bug.cgi?id=60576">http://bugs.ximian.com/show_bug.cgi?id=60576</a>) and here 
(<a class="moz-txt-link-freetext" href="http://bugs.gentoo.org/show_bug.cgi?id=63734">http://bugs.gentoo.org/show_bug.cgi?id=63734</a>).

This first code snippet exhibits the bug on a pure NPTL system:

using System;
using System.Threading;

class Test
{
        public static void Main( String[] args )
        {
                int i = 0;
                while( true ) {
                        Thread t = new Thread( new ThreadStart(Blah) );
                        t.Start();
                        i++;
                        Console.WriteLine( i+" threads" );
                }
        }

        private static void Blah() {
                Console.WriteLine( "starting thread" );
        }
}

Running this program inside gdb reveals that each of the threads created 
becomes a zombie as soon as it exits. Further investigation reveals that 
none of the mono thread cleanup code is being run (breaking on 
thread_cleanup() or handle_remove() gives no results) for any of the 
zombie threads. After the program has run for a certain length of time, 
the garbage collector is invoked, which forces a world stop of all 
threads. If the garbage collector is invoked when a zombie thread is 
present, mono_gc_stop_world() is called which iterates over the threads 
hashtable calling gc_stop_world() on each entry, which in turn calls 
SuspendThread() on the each. But because the thread cleanup code hasn't 
been run (in particular, handle_remove() which removes the thread handle 
from the hashtable), SuspendThread() gets called for threads which don't 
exist, or are zombies. The offending code appears to be:

while (MONO_SEM_WAIT (&amp;thread-&gt;suspend_sem) != 0 &amp;&amp; errno == EINTR);


in _wapi_timed_thread_suspend(), which indirectly calls 
pthread_cond_wait() for a condition variable that is not going to be 
triggered, because the other thread is a zombie.

As far as I can tell, mono_thread_manage runs it's 'join' loop once, at 
which point it waits for eternity inside WaitForMultipleObjectsEx() 
which is called from wait_for_tids(). Because of this, the 
thread_cleanup() call in wait_for_tids() is never reached, not for any 
of the threads.

I'm going to continue investigating this. Any help would be greatly 
appreciated.

    </pre>
  </blockquote>
  <pre wrap=""><!---->
Is that happening with CVS HEAD and not on 1.0? I removed some code to
fix this bug:
<a class="moz-txt-link-freetext" href="http://bugzilla.ximian.com/show_bug.cgi?id=65379">http://bugzilla.ximian.com/show_bug.cgi?id=65379</a>

and that might be the cause of yours if you're using CVS HEAD.

-Gonzalo


_______________________________________________
Mono-devel-list mailing list
<a class="moz-txt-link-abbreviated" href="mailto:Mono-devel-list@lists.ximian.com">Mono-devel-list@lists.ximian.com</a>
<a class="moz-txt-link-freetext" href="http://lists.ximian.com/mailman/listinfo/mono-devel-list">http://lists.ximian.com/mailman/listinfo/mono-devel-list</a>


  </pre>
</blockquote>
Yes, I have been using cvs HEAD. I switched back to version 1.0.1 and
this problem (handle_remove() not being called) was not present
anymore. However, the program still freezes during a garbage
collection. Is it possible that a thread exits, and the garbage
collector is called in another thread before handle_remove() is called
for the exiting thread? <br>
<br>
It appears not to be the case if the following output is anything to go
by. I've built mono-1.0.1 with THREAD_DEBUG, THREAD_WAIT_DEBUG, and
LIBGC_DEBUG defined in metadata/threads.c. I also modified the
g_message calls in handle_store and handle_remove to be a bit more
descriptive. This the output of the thread test case run inside gdb.<br>
<br>
<pre>starting thread
** Message: : returning 0x8230700
** Message: : (1098329008) Done launching thread 0x8230700 (1100430256)
197 threads
** Message: : returning 0x80fae00
** Message: : joining thread handle 0xd7d, -1 ms
** Message: : (1100430256) Abort requested for 0x8230700 (1100430256)
** Message: : returning 0x8230700
** Message: : returning 0x8230700
** Message: : removing thread ID 1100430256
** Message: : returning (nil)
** Message: : join successful
** Message: : Trying to start a new thread: this (0x8230690) start (0x8241b18)
[Thread 1100430256 (zombie) exited]
[New Thread 1102531504 (LWP 1187)]
** Message: : Started thread ID 1102531504 (handle 0xd80)
** Message: : (1098329008) Launching thread 0x8230690 (1102531504)
** Message: : storing thread 0x8230690 ID 1102531504
** Message: : (1098329008) waiting for thread 0x8230690 (1102531504) to start
** Message: : (1102531504) Start wrapper
** Message: : returning 0x8230690
** Message: : (1102531504,985) Setting thread stack to 0x41b749ec
** Message: : (1102531504) Setting current_object_key to 0x8230690
** Message: : (1098329008) Done launching thread 0x8230690 (1102531504)
198 threads
** Message: : returning 0x80fae00
** Message: : joining thread handle 0xd80, -1 ms
** Message: : returning 0x8230690
starting thread
** Message: : returning 0x8230690
** Message: : (1102531504) Abort requested for 0x8230690 (1102531504)
** Message: : returning 0x8230690
** Message: : returning 0x8230690
** Message: : join successful
** Message: : Trying to start a new thread: this (0x8230620) start (0x8241a78)
** Message: : removing thread ID 1102531504
** Message: : returning (nil)
[Thread 1102531504 (zombie) exited]
[New Thread 1100430256 (LWP 1188)]
Initiating full world-stop collection 4 after 466576 allocd bytes

</pre>
Everything seems to be ok here. However, if I break on
mono_gc_stop_world, the breakpoint isn't hit.<br>
<br>
Scott.
</body>
</html>