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 [EMAIL PROTECTED] 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: [EMAIL PROTECTED] +ReportedBy: [EMAIL PROTECTED] +QAContact: [EMAIL PROTECTED] +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 [EMAIL PROTECTED] 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 [EMAIL PROTECTED] 2006-06-12 18:34 ------- +*** Bug 78615 has been marked as a duplicate of this bug. *** + +------- Additional Comments From [EMAIL PROTECTED] 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). _______________________________________________ mono-bugs maillist - [email protected] http://lists.ximian.com/mailman/listinfo/mono-bugs
