Bug 798 - Monotouch should initialize Cocoa frameworks thread locks as per apple documentation
Summary: Monotouch should initialize Cocoa frameworks thread locks as per apple docume...
Alias: None
Product: iOS
Classification: Xamarin
Component: Xamarin.iOS.dll ()
Version: 3.x
Hardware: PC Other
: --- critical
Target Milestone: Untriaged
Assignee: Bugzilla
Depends on:
Reported: 2011-09-14 02:50 UTC by Jamie Briant
Modified: 2011-09-15 19:40 UTC (History)
3 users (show)

Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description Jamie Briant 2011-09-14 02:50:46 UTC

"For multithreaded applications, Cocoa frameworks use locks and other forms of internal synchronization to ensure they behave correctly. To prevent these locks from degrading performance in the single-threaded case, however, Cocoa does not create them until the application spawns its first new thread using the NSThread class. If you spawn threads using only POSIX thread routines, Cocoa does not receive the notifications it needs to know that your application is now multithreaded. When that happens, operations involving the Cocoa frameworks may destabilize or crash your application.

To let Cocoa know that you intend to use multiple threads, all you have to do is spawn a single thread using the NSThread class and let that thread immediately exit. Your thread entry point need not do anything. Just the act of spawning a thread using NSThread is enough to ensure that the locks needed by the Cocoa frameworks are put in place.

If you are not sure if Cocoa thinks your application is multithreaded or not, you can use the isMultiThreaded method of NSThread to check."

When I check NSThread.IsMultiThreaded from inside a C# Thread, it returns false.
Comment 1 Miguel de Icaza [MSFT] 2011-09-14 18:53:51 UTC
What is the scenario that is failing for you?

And would you mind doing this to your application to figure out if this is the fix you are looking for?

Before you call the UIApplication.Main in your mina method, can you create an NSThread and launch it?
Comment 2 Jamie Briant 2011-09-15 01:04:06 UTC
I'll detail my bug below, but may I ask, under what situation you believe it to be appropriate when using managed Threads to *not* initialize the iOS frameworks mutexes? Calling an iOS framework that relies on these mutexes is guaranteed to cause problems. How do we know which iOS API calls use these mutexes? We can't.

I've been doing iOS for over two years now, and this was the first I'd heard of this. I've never had to worry because I used NSThreads in my natively coded apps.

I believe that the onus falls on Mono to initialize the mutexes. The instructions are clear: if you use pthreads, and you use iOS frameworks, you must initialize the mutexes. Monotouch uses pthreads, and monotouch uses iOS frameworks.
Comment 3 Jamie Briant 2011-09-15 01:05:40 UTC
Here's my bug. It may or not be caused by NSThread.IsMultiThreaded being false. But it lead me to the documentation on it.

I have an utterly random bug that results in crashes (NullRefs and SIGSEGVs) in random places. Often the stack is unavailable higher than where the problem happened, which suggest to me that a) the stack is blown and b) the stack was blown while the thread was asleep, it woke up, loaded some dodgy values, and then called the code which then crashed.

When I first had the problem (about a month ago), I git-bisected the problem and the check-in which broke it could not possibly have caused the error. It was just unlucky.

Creating the project as an XCode project and running that caused the problem to go away (Geoff helped me immensely getting that working). Running in debug mode makes the problem go away. Eventually after bashing my head trying different things on the bistected build, and I gave up and tried doing things with HEAD, and the problems went away.

Not surprisingly they came back yesterday, and it was then that I noticed the stack state and that looks like another thread bombing this one's stack. So thats when I started looking for thread related issues.
Comment 4 Jamie Briant 2011-09-15 01:08:29 UTC
Btw: After a few changes, I could not get my app to reproduce the bug - even backtracking. Otherwise I would totally try adding just that NSThread init to main and seeing what happened.

Of course, if I added that line, and it fixed the problem, it wouldn't actually prove that NSThread fixed it, because adding any given line of code may make the code go away. =(
Comment 5 Jamie Briant 2011-09-15 01:42:44 UTC
Comment 6 Miguel de Icaza [MSFT] 2011-09-15 01:54:48 UTC

Agreed, MonoTouch will be updated to address this issue, but I wanted to find the use case that was failing.
Comment 7 Jamie Briant 2011-09-15 02:48:22 UTC
The problem is how do you debug such a thing? Normally when one has thread bugs, they are because a mutex isn't being used somewhere it should, or something like that. 

But that's not what we have here. Here we have a (supposedly) working framework, with mutexes that we are deliberately disabling! To "repro" these framework "bugs", we have to deliberately turn off all mutexes and then "see what happens". What would the purpose of that be? 

It would certainly be useful to me to know that *my* bug is caused by not turning on thread-safety in iOS, yes. Unfortunately, that will be impossible to prove. Lets say calling, or not calling the NSThread start, fixes/hides the bug. Did the bug go away because it was caused by iOS framework's lack of mutexes? Or did it go away simply because the mutexes introduced new timing, and the timing suppressed the bug?

Really the thing to do is slap a hardware breakpoint on the stack that's being bombed and see where it happens. However, I don't believe there is a way to do that without making an XCode build, and the last time I did that (with Geoff's help) it just made the bug go away. I was sad.

I wonder if rooting the device will allow me to attach a debugger from ssh?
Comment 8 Rolf Bjarne Kvinge [MSFT] 2011-09-15 19:40:43 UTC
This has now been fixed.