Bug 6654 - AutoResetEvent state is getting corrupted
Summary: AutoResetEvent state is getting corrupted
Alias: None
Product: Android
Classification: Xamarin
Component: BCL Class Libraries ()
Version: 4.2.x
Hardware: PC Other
: --- normal
Target Milestone: ---
Assignee: Bugzilla
Depends on:
Reported: 2012-08-22 19:40 UTC by Gerardo
Modified: 2012-09-13 22:23 UTC (History)
4 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 Gerardo 2012-08-22 19:40:32 UTC
We're experiencing a strange bug, that unfortunately, cannot replicate at will. It is very sporadic.
It has only surfaced on Samsung Galaxy S3 phones running Android 4.04

We have a static class, that has a static AutoResetEvent member that is created upon declaration:

 public static class TCPClient2 {
      static AutoResetEvent _dataSentSemaphore = new AutoResetEvent(false);

Basically there's no code aliasing the private _dataSentSemaphore reference, no code is reasigning the reference to something else or setting it to null, and no code is either calling _dataSentSemaphore.Dispose() or wrapping the reference with a using() statement. 

Then eventually, the application will crash while calling  _dataSentSemaphore.Set(), throwing the following Exception:

08-22 16:48:44.496 E/OBSMOBILE(20319): TCPClient2: Could not receive response [The object was used after being disposed.] ->   at System.Runtime.InteropServices.SafeHandle.DangerousGetHandle () [0x00000] in <filename unknown>:0 
08-22 16:48:44.496 E/OBSMOBILE(20319):   at System.Threading.WaitHandle.get_Handle () [0x00000] in <filename unknown>:0 
08-22 16:48:44.496 E/OBSMOBILE(20319):   at System.Threading.EventWaitHandle.Set () [0x00000] in <filename unknown>:0 
08-22 16:48:44.496 E/OBSMOBILE(20319):   at (wrapper remoting-invoke-with-check) System.Threading.EventWaitHandle:Set ()
08-22 16:48:44.496 E/OBSMOBILE(20319):   at Obsidian.Lib.Net.TCPClient2.state_Receive () [0x00000] in <filename unknown>:0

How can the internal state of the AutoResetEvent hold a reference to a disposed object, if there is no code actively disposing the AutoResetEvent and a live reference to it is being held for the lifetime of the application?

Thanks for any pointers on how to solve this. Since this is an AutoResetEvent that is coordinating work between two threads, catching the exception and recreating the AutoResetEvent instance is not an option.
Comment 2 Gerardo 2012-08-28 11:21:23 UTC
Hello Michal,

Could you please test if you are compiling your application supporting only the armeabi architecture?

We were compiling on plain armeabi, and since we added armeabi-v7a we haven't experienced the crash  (I know it is still to early to claim victory, but I think it's worth the try).

I read in another bug report that some sort of patch had to be done for armeabi code to be able to run on multi-core ARM cpus, so maybe this could be related to that patch.

Good Luck!
Comment 3 Michal Dobrodenka 2012-08-28 11:26:03 UTC
You are right, my architectures were only armeabi & x86, I'm going to check all three of them and see what will happen.
Comment 4 Gerardo 2012-08-30 15:31:26 UTC
Confirmed, our solution compiled as armeabi-v7a has been working more than 72 hours on 3 test phones without problems (we couldn't get past 24 hours without incident).
Comment 5 Jonathan Pryor 2012-08-31 12:16:58 UTC
This is a regression; the armeabi CPU tying code was inadvertently removed. In January 2012. Oops.

(This probably impacts Mono for Android 4.1+, though I'm not entirely sure.)

To demonstrate, launch a Release app with only the armeabi runtime available.

    $ adb shell ps | grep your.package.name
    $ adb shell cat /proc/PID/status
    Cpus_allowed:	3
    Cpus_allowed_list:	0-1

More than one CPU is a bug, and leads to pain and suffering.

When things are working property, /proc/PID/status will instead contain:

    Cpus_allowed:	1
    Cpus_allowed_list:	0

Fixed in master/97b760fa and monodroid-4.2.5-branch/9c5dcda0.
Comment 6 Gerardo 2012-09-11 14:20:28 UTC
Thank you very much Jonathan, for looking and fixing this issue.

Comment 7 Jonathan Pryor 2012-09-11 14:33:55 UTC
@Gerado: In theory, the final/stable 4.2.5 release has this fix.

In practice, I don't think it was fixed; see #7013. I'm starting to believe that this is unfixable, and the only safe solution is to either include only the armeabi-v7a runtime (if you don't need to support older ARMv5 devices), or include both the armeabi and armeabi-v7a runtimes.