> >From: Anthony Bowker <anth...@flowol.com>
> >Date: Tue 13 Oct 2009 21:41:20 GMT+02:00
> >To: "users@lists.monobjc.net" <users@lists.monobjc.net>
> >Subject: RE: [us...@lists.monobjc.net] Re: [us...@lists.monobjc.net]  
> >Feeback Wanted on Snow Leopard
> >Reply-To: "users@lists.monobjc.net" <users@lists.monobjc.net>
> >
> >I haven't been able to devote much time over the past couple of  
> >weeks to
> >building mono with the patch and testing my app.  My apologies for  
> >not being
> >able to help out more.
> >
> >I've just noticed Sledge Ham's stack trace in the bug
> >(https://bugzilla.novell.com/show_bug.cgi?id=537764) and since the
> >notification in the stack is dealloc, I've been reading about  
> >monobjc's
> >method swizzling on dealloc.
> >
> >How about this hypothesis: In Snow Leopard, there are some foreign  
> >threads
> >created by the ObjectiveC runtime which do some stuff with  
> >NSObjects, and
> >eventually their NSObject:dealloc method is called, this is swizzled  
> >by
> >monobjc which runs the managed NSObjectImposter.dealloc method to  
> >maintain
> >the managed wrapper class instances.  This is a managed method, so  
> >mono
> >kicks into gear and mono_jit_thread_attach and friends are called to  
> >add the
> >thread to the GC_threads-array.  This is a peculiar thread, it goes  
> >away
> >later without notification to the mono runtime, and causes the crash.
> >
> >It would be cool if we could swizzle for only the threads we care  
> >about.  Or
> >perhaps we should swizzle with native code first...
> >
Anthony,

What about the following hypothesis:
In snow leopard there are some foreign threads created by/used by the
ObjectiveC runtime which do some stuff with NSObjects. 
One of the actions is that this thread is registered with mono and
mono registers a thread specific data with clean up function. 


Later some object/function does some things with NS objects.. the
runtime now allocates a new NSobject and stores it in some thread
specific data with a clean up handler...  

Now for some reason this thread decides to exit (probably because the
app lost focus or so).. Now the pthread calls the pthread_exit()
function.

One of the tasks of the pthread_exit function is to clean up all
thread specific data.. The first thing it does is deregister itself
from the GC.. 
The second thing it does, is proces the other thread specific cleanup
handlers, which is the dealloc-function... This is picked up by mono
which does not find the thread (it just go cleaned up in the previous
step) so it reregisters this thread and does all required stuff
(perform the dealloc on the objects). When this clean up has
completed, the cleanup handler returns and the thread thinks it
cleaned up everything.. 

but... wait.. the dealloc cause a reregistration of the thread.. and
the thread exited.. We have an inconsistecy between the threads which
are still alive (accroding to the processor/OS) and which threads do
exists according to mono's gc.. 

The problem is that to my knowledge pthreads do not specify an order
in which thread-specific cleanup is implemented... To my feeling we
should find a way to make sure we do not reregister threads when they
are being cleaned up. as pthreads do not guarantee any order we are
kinda screwed...


Ideas I have, but which are probably not ok:

1) When the thread is deregistered we call ourselves
pthread_tsd_cleanup...
This will make sure all other thread specific data is gone before we
return from the deregister functions... I am not sure if this will
work however, because we would have a nested
pthread_tsd_cleanup().. Chances are very high that the outer
pthread_tsd_cleanup will crash because data structures have changed.. 

2) We try to implement something which makes sure that we do not
reregister a thread which is quiting.. how? 
a) we add a new thread
specific data with clean up and we 'hope' that it gets called again
after the other objects are cleaned.. This is also very dependent on
the pthread implementation, so it is probably not a good way

b) while deregistering we add a new tsd which says that the thread is
quitting... before registering a function we check that this tsd does
not exist.. If it does we do not reregister the thread. problem is
that this new tsd might be cleanedup before the other objects and we
run into the same issue..


I think that without a good insight of the pthread_tsd_cleanup() we
can make guesses on what is happening and probably introduce a lot of
new issues ;-(


Maybe we should think in a completely other direction... Instead of
deleting the thread when the deregister function is called, we just
mark the thread stale (like laurent proposed) and we register the time
at which the thread went stale... Then at a later time we remove all
threads which were stale for at least x (10?) seconds or
so... Question I have is.. what if after 5 seconds a new thread is
fired with the same threadid.. we will probably again run into an
inconsistent state...

Another idea .. which is a radical change.. Instead of trying to
register the threads, can't we just ask mach which threads are alive
and suspend all these threads when the GC runs? this way we do not
rely on any pthreads mechanism... 

Other ideas are welcome...

Sledge


> >I realize this is probably the wrong place to be asking, but does  
> >anyone
> >know if the other mono-objectiveC bridges have the same problem?
> >
> >I'm very new to understanding swizzling and the mono GC, so if what  
> >I've
> >written above sounds like nonsense, it probably is :-)
> >
> >Many thanks for everyone's efforts here.
> >
> >Anthony
> 

Reply via email to