[Mono-bugs] [Bug 78628][Nor] New - mono leaks mach ports

bugzilla-daemon at bugzilla.ximian.com bugzilla-daemon at bugzilla.ximian.com
Tue Jun 13 18:05:24 EDT 2006


Please do not reply to this email- if you want to comment on the bug, go to the
URL shown below and enter your comments there.

Changed by allan at imeem.com.

http://bugzilla.ximian.com/show_bug.cgi?id=78628

--- shadow/78628	2006-06-13 18:05:24.000000000 -0400
+++ shadow/78628.tmp.20224	2006-06-13 18:05:24.000000000 -0400
@@ -0,0 +1,177 @@
+Bug#: 78628
+Product: Mono: Runtime
+Version: 1.1
+OS: unknown
+OS Details: OS X 10.4.6, PPC and x86
+Status: NEW   
+Resolution: 
+Severity: Unknown
+Priority: Normal
+Component: misc
+AssignedTo: dick at ximian.com                            
+ReportedBy: allan at imeem.com               
+QAContact: mono-bugs at ximian.com
+TargetMilestone: ---
+URL: 
+Summary: mono leaks mach ports
+
+Please fill in this template when reporting a bug, unless you know what you are doing.
+Description of Problem:
+
+Mono leaks mach ports. Sample code and examination of the darwin_stop_world.c suggests that 
+the problem is at least partially threading/garbage collection related.
+
+Steps to reproduce the problem:
+1. Here is sample code the reproduces the problem. It is also available at http://blargle.com/
+~allan/leaky.tar.bz2 . Note that there are two samples: one managed and one un-managed.
+
+The managed example:
+
+using System;
+using System.Collections;
+using System.Text;
+using System.Threading;
+
+namespace blargle
+{
+        class Leaky
+        {
+                private static int thread_chunksize = 256; 
+                static void Main(string[] args)
+                {
+                        ArrayList threads = new ArrayList(thread_chunksize);
+                        while(true)
+                        {
+                                for(int i = 0; i < thread_chunksize; i++)
+                                {
+                                        Thread newThread = new Thread(new ThreadStart(Blargle));
+                                        newThread.Start();
+                                        threads.Add(newThread);
+                                }
+
+                                foreach(Thread thread in threads)
+                                {
+                                        thread.Join();
+                                }
+                                
+                                Thread.Sleep(2000);
+                        }
+                }
+
+                static void Blargle()
+                {
+                        //just doing stuff to cause memory allocation.
+                        StringBuilder stringBuilder = new StringBuilder();
+                        
+                        for(int i = 0; i < 555; i++)
+                        {
+                                stringBuilder.Append("Blargle");
+                                string falargle = stringBuilder.ToString();
+                        }
+                }
+        }
+}
+
+The embedding example:
+
+#include <pthread.h>
+#include <mono/jit/jit.h>
+#include <mono/metadata/metadata.h>
+#include <mono/metadata/debug-helpers.h>
+#include <mono/metadata/object.h>
+#include <mono/metadata/threads.h>
+#include <mono/metadata/appdomain.h>
+
+#define CHUNK_THREADCOUNT 32
+
+static void *thread_function(void *monoDomain) {
+        printf("Attaching thread...\n");
+        MonoThread *monoThread = mono_thread_attach((MonoDomain *)monoDomain);
+        printf("Thread (%p) attached.\n", monoThread);
+
+        //normally, some threaded stuff would happen here.
+
+        printf("Detaching thread (%p)\n", monoThread);
+        mono_thread_detach(monoThread);
+        printf("Thread (%p) detached.\n", monoThread);
+}
+
+int main(int argc, char *argv[]) {
+
+        mono_set_defaults(0, mono_parse_default_optimizations(NULL));
+        MonoDomain *monoDomain = mono_jit_init("leaky");
+
+        while(TRUE) {
+                pthread_t threads[CHUNK_THREADCOUNT];
+                int i;
+
+                for(i = 0; i < CHUNK_THREADCOUNT; i++)
+                        pthread_create(threads + i, NULL, thread_function, monoDomain);
+
+
+                for(i = 0; i < CHUNK_THREADCOUNT; i++) {
+                        pthread_join(threads[i], NULL);
+                        pthread_detach(threads[i]);
+                }
+
+                sleep(1);
+        }
+
+        return(0);
+}
+
+Actual Results:
+
+In both examples, port usage (as reported by Activity Monitor, under the "Statistics" tab of the 
+process inspector) rises without bound.
+
+The managed example will sometimes die like this:
+
+cromulent:~/mono/leaky allan$ mono leaky.exe 
+
+** (leaky.exe:25370): WARNING **: CreateThread: error creating thread handle
+
+** (leaky.exe:25370): WARNING **: ves_icall_System_Threading_Thread_Thread_internal: 
+CreateThread error 0x1f
+
+Unhandled Exception: System.SystemException: Thread creation failed.
+  at System.Threading.Thread.Start () [0x00000] 
+  at blargle.Leaky.Main (System.String[] args) [0x00000] 
+
+** (leaky.exe:25370): WARNING **: _wapi_thread_apc_pending: error looking up thread handle 
+0x108
+
+The embedding example will eventually bomb out like this:
+
+thread_terminate(mach_thread_self()) failed: (ipc/send) invalid destination port
+
+Expected Results:
+
+Port count should fluctuate, but not rise without bound. Programs should definitely not bomb 
+out.
+
+How often does this happen? 
+
+Always.
+
+Additional Information:
+I will attach a GC patch that seems to halve the number of ports leaked per thread chunk, at least 
+for the embedding example. The patch is rough and has whitespace changes I made just so I 
+could visually parse the code, as well as comment-out debugging GC_printfs.
+
+------- Additional Comments From allan at imeem.com  2006-06-12 18:33 -------
+Created an attachment (id=17166)
+rough patch for darwin_stop_world.c that reduces mach port leaks
+
+
+------- Additional Comments From allan at imeem.com  2006-06-12 18:34 -------
+*** Bug 78615 has been marked as a duplicate of this bug. ***
+
+------- Additional Comments From allan at imeem.com  2006-06-13 18:05 -------
+At Miguel's suggestion, I tried using an upstream version of libgc instead of the one included 
+with Mono. Using libgc 6.6, it looks like the port leaks caused by thread registration (seen 
+with the embedded sample code) have gone away, but the leaks that seem to be caused by 
+garbage collection are still present. Also, 6.6 seems to have a pretty bad memory leak that 
+does not exist in the Mono SVN version of libgc. I will attach a version of my previous GC 
+patch that fixes the memory leak and also calls mach_port_deallocate() (libgc 6.6 was also 
+missing those calls).


More information about the mono-bugs mailing list