Bug 10379 - NullReferenceException in AppDomain.UnhandledException handler
Summary: NullReferenceException in AppDomain.UnhandledException handler
Status: NEEDINFO
Alias: None
Product: Android
Classification: Xamarin
Component: General (show other bugs)
Version: 4.4.x
Hardware: PC Windows
: High normal
Target Milestone: ---
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2013-02-18 11:49 UTC by Sebastian Krysmanski
Modified: 2014-01-10 21:55 UTC (History)
3 users (show)

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


Attachments

Description Sebastian Krysmanski 2013-02-18 11:49:35 UTC
Create a new project (default Mono for Android target), and provide the following for Activity1.cs:

  using System;
  using Android.App;
  using Android.OS;
  using Android.Util;
  using Android.Widget;

  namespace ExceptionMessageBug {
    [Activity(Label = "ExceptionMessageBug", MainLauncher = true, Icon = "@drawable/icon")]
    public class Activity1 : Activity {
      protected override void OnCreate(Bundle bundle) {
        base.OnCreate(bundle);
        SetContentView(Resource.Layout.Main);

        AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;

        Button button = FindViewById<Button>(Resource.Id.MyButton);
        button.Click += OnButtonClick;
      }

      private void OnButtonClick(object sender, EventArgs eventArgs) {
        throw new Java.Lang.RuntimeException("This is a Java exception.");
      }

      private void OnUnhandledException(object sender, UnhandledExceptionEventArgs e) {
        var javaException = e.ExceptionObject as Java.Lang.RuntimeException;
        if (javaException != null) {
          try {
            // this will trigger a "System.NullReferenceException" exception.
            string msg = javaException.Message;
          }
          catch (NullReferenceException e2) {
            string err = e2.ToString();
          }

          try {
            // This will trigger a NullReferenceException as well
            Log.Error("IamBuggy", "Some text");
          }
          catch (NullReferenceException e2) {
            string err = e2.ToString();
          }
        }
      }
    }
  }

When you hit the button, a Java exception will be thrown. It'll then be handled by "OnUnhandledException()".

However, the Android binding seem to be "shut down" at this moment. "System.NullReferenceExceptions" will be thrown in lines 29 and 37:

"string msg = javaException.Message;"
  System.NullReferenceException: Object reference not set to an instance of an object
    at Android.Runtime.JNIEnv.CallObjectMethod (IntPtr jobject, IntPtr jmethod) [0x00000] in /Users/builder/data/lanes/monodroid-mac-monodroid-4.4-series/6418373f/source/monodroid/src/Mono.Android/src/Runtime/JNIEnv.g.cs:129 
    at Java.Lang.Throwable.get_Message () [0x0003e] in /Users/builder/data/lanes/monodroid-mac-monodroid-4.4-series/6418373f/source/monodroid/src/Mono.Android/platforms/android-8/src/generated/Java.Lang.Throwable.cs:175 
    at ExceptionMessageBug.Activity1.OnUnhandledException (System.Object sender, System.UnhandledExceptionEventArgs e) [0x00019] in d:\Bugs\MonoDroid\ExceptionMessageBug\ExceptionMessageBug\Activity1.cs:29

"Log.Error(...)"
  System.NullReferenceException: Object reference not set to an instance of an object
    at (wrapper delegate-invoke) <Module>:invoke_intptr__this___intptr_intptr_string_string (intptr,intptr,string,string)
    at Android.Runtime.JNIEnv.GetStaticMethodID (IntPtr jclass, System.String name, System.String sig) [0x00000] in /Users/builder/data/lanes/monodroid-mac-monodroid-4.4-series/6418373f/source/monodroid/src/Mono.Android/src/Runtime/JNIEnv.g.cs:740 
    at Android.Util.Log.Error (System.String tag, System.String msg) [0x00014] in /Users/builder/data/lanes/monodroid-mac-monodroid-4.4-series/6418373f/source/monodroid/src/Mono.Android/platforms/android-8/src/generated/Android.Util.Log.cs:60 
    at ExceptionMessageBug.Activity1.OnUnhandledException (System.Object sender, System.UnhandledExceptionEventArgs e) [0x00031] in d:\Bugs\MonoDroid\ExceptionMessageBug\ExceptionMessageBug\Activity1.cs:37
Comment 1 Miguel de Icaza [MSFT] 2013-05-22 14:09:42 UTC
In this case, we should decide on a policy about what to do about this.

This will require some research on our end, but raising the visibiltiy level.
Comment 2 Jonathan Pryor 2014-01-10 21:55:40 UTC
I am not able to repro your NullReferenceException with Xamarin.Android 4.11 alpha. Running the app, I now get:

> I/MonoDroid( 6778): UNHANDLED EXCEPTION: Java.Lang.RuntimeException: Exception of type 'Java.Lang.RuntimeException' was thrown.
> I/MonoDroid( 6778): at Scratch.Bxc10379.Activity1.OnButtonClick (object,System.EventArgs) <0x00044>
> I/MonoDroid( 6778): at Android.Views.View/IOnClickListenerImplementor.OnClick (Android.Views.View) <0x00047>
> I/MonoDroid( 6778): at Android.Views.View/IOnClickListenerInvoker.n_OnClick_Landroid_view_View_ (intptr,intptr,intptr) <0x0005f>
> I/MonoDroid( 6778): at (wrapper dynamic-method) object.724bd5bf-8daf-4f91-a6a2-8bead8354e0b (intptr,intptr,intptr) <0x00043>
> I/MonoDroid( 6778): 
> I/MonoDroid( 6778):   --- End of managed exception stack trace ---
> I/MonoDroid( 6778): java.lang.RuntimeException: This is a Java exception.
> I/MonoDroid( 6778):     at mono.android.view.View_OnClickListenerImplementor.n_onClick(Native Method)
> I/MonoDroid( 6778):     at mono.android.view.View_OnClickListenerImplementor.onClick(View_OnClickListenerImplementor.java:29)
> I/MonoDroid( 6778):     at android.view.View.performClick(View.java:4438)
> I/MonoDroid( 6778):     at android.view.View$PerformClick.run(View.java:18422)
> I/MonoDroid( 6778):     at android.os.Handler.handleCallback(Handler.java:733)
> I/MonoDroid( 6778):     at android.os.Handler.dispatchMessage(Handler.java:95)
> I/MonoDroid( 6778):     at android.os.Looper.loop(Looper.java:136)
> I/MonoDroid( 6778):     at android.app.ActivityThread.main(ActivityThread.java:5017)
> I/MonoDroid( 6778):     at java.lang.reflect.Method.invokeNative(Native Method)
> I/MonoDroid( 6778):     at java.lang.reflect.Method.invoke(Method.java:515)
> I/MonoDroid( 6778):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
> I/MonoDroid( 6778):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
> I/MonoDroid( 6778):     at dalvik.system.NativeStart.main(Native Method)
> W/dalvikvm( 6778): JNI WARNING: JNI function GetMethodID called with exception pending
> W/dalvikvm( 6778):              in Lmono/android/view/View_OnClickListenerImplementor;.n_onClick:(Landroid/view/View;)V (GetMethodID)
> W/dalvikvm( 6778): Pending exception is:
> I/dalvikvm( 6778): java.lang.RuntimeException: This is a Java exception.
... 
> E/dalvikvm( 6778): VM aborting
> E/mono-rt ( 6778): Stacktrace:
> E/mono-rt ( 6778): 
> E/mono-rt ( 6778):   at <unknown> <0xffffffff>
> E/mono-rt ( 6778):   at (wrapper managed-to-native) object.wrapper_native_0x41540c59 (intptr,intptr,string,string) <0xffffffff>
> E/mono-rt ( 6778):   at (wrapper delegate-invoke) <Module>.invoke_intptr__this___intptr_intptr_string_string (intptr,intptr,string,string) <0xffffffff>
> E/mono-rt ( 6778):   at Android.Runtime.JNIEnv.GetMethodID (intptr,string,string) <0x00093>
> E/mono-rt ( 6778):   at Java.Lang.Throwable.get_Message () <0x00047>
> E/mono-rt ( 6778):   at Scratch.Bxc10379.Activity1.OnUnhandledException (object,System.UnhandledExceptionEventArgs) <0x0008b>
> E/mono-rt ( 6778):   at (wrapper runtime-invoke) <Module>.runtime_invoke_void__this___object_object (object,intptr,intptr,intptr) <0xffffffff>

This isn't entirely desirable, but!

The purpose of AppDomain.UnhandledException is to allow you to find out information about the exception before the app dies. The app WILL die; you're just getting a chance to do something BEFORE it dies.

The problem with the above stack trace is that instead of Mono aborting the process, Dalvik did.

Dalvik aborted the process because you had a pending Java-side exception, then called Log.Error(), and Dalvik (JNI?) doesn't like calling JNI methods when a Java exception is pending, so it nuked the process from orbit.

The one thing I'm not sure about is why there was a pending Java-side exception. I don't think that `throw new Java.Lang.RuntimeException("This is a Java exception.");` will do that...

Regardless, we do know of issues with exception propagation (Bug #7634), but this is not quite the same.

Note You need to log in before you can comment on or make changes to this bug.