Bug 7634 - Managed->Java->Managed Exception Propagation is broken
Summary: Managed->Java->Managed Exception Propagation is broken
Status: VERIFIED FIXED
Alias: None
Product: Android
Classification: Xamarin
Component: Mono runtime / AOT Compiler ()
Version: 4.2.x
Hardware: PC Mac OS
: High normal
Target Milestone: 5.1
Assignee: Rodrigo Kumpera
URL:
: 8900 16903 ()
Depends on:
Blocks: 2461
  Show dependency tree
 
Reported: 2012-10-03 16:27 UTC by Jonathan Pryor
Modified: 2015-04-20 08:50 UTC (History)
15 users (show)

Tags:
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:
Status:
VERIFIED FIXED

Description Jonathan Pryor 2012-10-03 16:27:49 UTC
Create a new project (default Mono for Android target), and provide the following for Activity1.cs:

  using System;

  using Android.App;
  using Android.Content;
  using Android.Runtime;
  using Android.Views;
  using Android.Widget;
  using Android.OS;

  namespace Scratch.ExceptionPropogation
  {
    [Activity (Label = "Scratch.ExceptionPropogation", MainLauncher = true)]
    public class Activity1 : Activity
    {
      int count = 1;

      protected override void OnCreate (Bundle bundle)
      {
        base.OnCreate (bundle);

        // Set our view from the "main" layout resource
        SetContentView (Resource.Layout.Main);

        // Get our button from the layout resource,
        // and attach an event to it
        Button button = FindViewById<Button> (Resource.Id.myButton);

        button.Click += delegate {
          button.Text = string.Format ("{0} clicks!", count++);

          var r = new Runnable ();
          try {
            IntPtr run = JNIEnv.GetMethodID (r.Class.Handle, "run", "()V");
            JNIEnv.CallVoidMethod(r.Handle, run);
            Console.WriteLine ("wtf?");
          } catch (Exception e) {
            var a = this.Application;
            Console.WriteLine ("Exception caught! {0}", e);
          }
        };
      }
    }

    class Runnable : Java.Lang.Object, Java.Lang.IRunnable {

      public Runnable ()
      {
      }

      public void Run ()
      {
        Console.WriteLine ("Runnable.Run!");
        Console.WriteLine (
            new System.Diagnostics.StackTrace (true).ToString ());
        throw new Java.Lang.RuntimeException ("Goodbye, cruel world!");
      }
    }
  }

Build + Run, then click the app's button. Expected results, nothing; app continues to run.

Actual results: JNI crash

>  Runnable.Run!
>     at Java.Lang.IRunnableInvoker.n_Run(IntPtr jnienv, IntPtr native__this)
>     at System.Object.6fe812e6-409e-4e73-af78-1fee4c29dcd3(IntPtr , IntPtr )
>     at Android.Runtime.JNIEnv.CallVoidMethod(IntPtr jobject, IntPtr jmethod)
>     at Scratch.ExceptionPropogation.Activity1+<OnCreate>c__AnonStorey0.<>m__0(System.Object , System.EventArgs ) in /Users/jon/Development/Projects/Scratch.ExceptionPropogation/Activity1.cs:line 34
>     at Android.Views.View+IOnClickListenerImplementor.OnClick(Android.Views.View v)
>     at Android.Views.View+IOnClickListenerInvoker.n_OnClick_Landroid_view_View_(IntPtr jnienv, IntPtr native__this, IntPtr native_v)
>     at System.Object.dd5ed973-0e47-42bf-9c5f-26fea5c31927(IntPtr , IntPtr , IntPtr )
>  Start proc com.metago.astro for service com.metago.astro/.jobs.JobService: pid=19143 uid=10109 gids={3003, 1015, 1028}
>  UNHANDLED EXCEPTION: Java.Lang.RuntimeException: Exception of type 'Java.Lang.RuntimeException' was thrown.
>  at Scratch.ExceptionPropogation.Runnable.Run () [0x0001a] in /Users/jon/Development/Projects/Scratch.ExceptionPropogation/Activity1.cs:54
>  at Java.Lang.IRunnableInvoker.n_Run (intptr,intptr) <IL 0x00009, 0x00037>
>  at (wrapper dynamic-method) object.6fe812e6-409e-4e73-af78-1fee4c29dcd3 (intptr,intptr) <0x0002b>
>  
>    --- End of managed exception stack trace ---
>  java.lang.RuntimeException: Goodbye, cruel world!
>  	at scratch.exceptionpropogation.Runnable.n_run(Native Method)
>  	at scratch.exceptionpropogation.Runnable.run(Runnable.java:29)
>  	at mono.android.view.View_OnClickListenerImplementor.n_onClick(Native Method)
>  	at mono.android.view.View_OnClickListenerImplementor.onClick(View_OnClickListenerImplementor.java:29)
>  	at android.view.View.performClick(View.java:4084)
>  	at android.view.View$PerformClick.run(View.java:16966)
>  	at android.os.Handler.handleCallback(Handler.java:615)
>  	at android.os.Handler.dispatchMessage(Handler.java:92)
>  	at android.os.Looper.loop(Looper.java:137)
>  	at android.app.ActivityThread.main(ActivityThread.java:4745)
>  	at java.lang.reflect.Method.invokeNative(Native Method)
>  	at java.lang.reflect.Method.invoke(Method.java:511)
>  	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
>  	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
>  	at dalvik.system.NativeStart.main(Native Method)
>  JNI WARNING: JNI method called with exception pending
>               in Lscratch/exceptionpropogation/Runnable;.n_run:()V (GetMethodID)
>  Pending exception is:
>  java.lang.RuntimeException: Goodbye, cruel world!
>    (raw stack trace not found)
>  "main" prio=5 tid=1 NATIVE
>    | group="main" sCount=0 dsCount=0 obj=0x40d61568 self=0x40c7bab0
>    | sysTid=19090 nice=0 sched=0/0 cgrp=apps handle=1074968112
>    | schedstat=( 0 0 0 ) utm=63 stm=23 core=0
>    #00  pc 00001260  /system/lib/libcorkscrew.so (unwind_backtrace_thread+27)
>    #01  pc 0005f8c4  /system/lib/libdvm.so (dvmDumpNativeStack(DebugOutputTarget const*, int)+35)
>    #02  pc 0005376c  /system/lib/libdvm.so (dvmDumpThreadEx(DebugOutputTarget const*, Thread*, bool)+303)
>    #03  pc 00053806  /system/lib/libdvm.so (dvmDumpThread(Thread*, bool)+25)
>    #04  pc 00038dc2  /system/lib/libdvm.so
>    #05  pc 00040faa  /system/lib/libdvm.so
>    at scratch.exceptionpropogation.Runnable.n_run(Native Method)
>    at scratch.exceptionpropogation.Runnable.run(Runnable.java:29)
>    at mono.android.view.View_OnClickListenerImplementor.n_onClick(Native Method)
>    at mono.android.view.View_OnClickListenerImplementor.onClick(View_OnClickListenerImplementor.java:29)
>    at android.view.View.performClick(View.java:4084)
>    at android.view.View$PerformClick.run(View.java:16966)
>    at android.os.Handler.handleCallback(Handler.java:615)
>    at android.os.Handler.dispatchMessage(Handler.java:92)
>    at android.os.Looper.loop(Looper.java:137)
>    at android.app.ActivityThread.main(ActivityThread.java:4745)
>    at java.lang.reflect.Method.invokeNative(Native Method)
>    at java.lang.reflect.Method.invoke(Method.java:511)
>    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
>    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
>    at dalvik.system.NativeStart.main(Native Method)
>  
>  VM aborting
>  Stacktrace:
>  
>    at (wrapper delegate-invoke) <Module>.invoke_intptr__this___intptr_intptr_string_string (intptr,intptr,string,string) <IL 0x00063, 0xffffffff>
>    at Android.Runtime.JNIEnv.GetMethodID (intptr,string,string) <IL 0x00012, 0x00053>
>    at Android.App.Activity.get_Application () <IL 0x00023, 0x00057>
>    at Scratch.ExceptionPropogation.Activity1/<OnCreate>c__AnonStorey0.<>m__0 (object,System.EventArgs) [0x0006d] in /Users/jon/Development/Projects/Scratch.ExceptionPropogation/Activity1.cs:37
>    at Android.Views.View/IOnClickListenerImplementor.OnClick (Android.Views.View) <IL 0x00017, 0x0005b>
>    at Android.Views.View/IOnClickListenerInvoker.n_OnClick_Landroid_view_View_ (intptr,intptr,intptr) <IL 0x00012, 0x0005b>
>    at (wrapper dynamic-method) object.dd5ed973-0e47-42bf-9c5f-26fea5c31927 (intptr,intptr,intptr) <IL 0x00012, 0x00033>
>    at (wrapper native-to-managed) object.dd5ed973-0e47-42bf-9c5f-26fea5c31927 (intptr,intptr,intptr) <IL 0x0001f, 0xffffffff>
>  JNI WARNING: JNI method called with exception pending
>               in Lscratch/exceptionpropogation/Runnable;.n_run:()V (NewString)
>  Pending exception is:
>  java.lang.RuntimeException: Goodbye, cruel world!
>    (raw stack trace not found)
>  "main" prio=5 tid=1 NATIVE
>    | group="main" sCount=0 dsCount=0 obj=0x40d61568 self=0x40c7bab0
>    | sysTid=19090 nice=0 sched=0/0 cgrp=apps handle=1074968112
>    | schedstat=( 0 0 0 ) utm=64 stm=23 core=0
>    #00  pc 00001260  /system/lib/libcorkscrew.so (unwind_backtrace_thread+27)
>    #01  pc 0005f8c4  /system/lib/libdvm.so (dvmDumpNativeStack(DebugOutputTarget const*, int)+35)
>    #02  pc 0005376c  /system/lib/libdvm.so (dvmDumpThreadEx(DebugOutputTarget const*, Thread*, bool)+303)
>    #03  pc 00053806  /system/lib/libdvm.so (dvmDumpThread(Thread*, bool)+25)
>    #04  pc 00038dc2  /system/lib/libdvm.so
>    #05  pc 0003c5d2  /system/lib/libdvm.so
>    at scratch.exceptionpropogation.Runnable.n_run(Native Method)
>    at scratch.exceptionpropogation.Runnable.run(Runnable.java:29)
>    at mono.android.view.View_OnClickListenerImplementor.n_onClick(Native Method)
>    at mono.android.view.View_OnClickListenerImplementor.onClick(View_OnClickListenerImplementor.java:29)
>    at android.view.View.performClick(View.java:4084)
>    at android.view.View$PerformClick.run(View.java:16966)
>    at android.os.Handler.handleCallback(Handler.java:615)
>    at android.os.Handler.dispatchMessage(Handler.java:92)
>    at android.os.Looper.loop(Looper.java:137)
>    at android.app.ActivityThread.main(ActivityThread.java:4745)
>    at java.lang.reflect.Method.invokeNative(Native Method)
>    at java.lang.reflect.Method.invoke(Method.java:511)
>    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
>    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
>    at dalvik.system.NativeStart.main(Native Method)
>  
>  VM aborting
>  
>  Unhandled Exception:
>  System.NullReferenceException: Object reference not set to an instance of an object
>  at Android.Runtime.JNIEnv.NewString (string) <IL 0x00032, 0x0006b>
>  at Android.Util.Log.Info (string,string) <IL 0x0002e, 0x00073>
>  at Android.Runtime.AndroidEnvironment.UnhandledException (System.Exception) <IL 0x00010, 0x00037>
>  at (wrapper dynamic-method) object.dd5ed973-0e47-42bf-9c5f-26fea5c31927 (intptr,intptr,intptr) <IL 0x0002a, 0x00087>
>  at (wrapper native-to-managed) object.dd5ed973-0e47-42bf-9c5f-26fea5c31927 (intptr,intptr,intptr) <IL 0x00019, 0x00043>
Comment 1 Jonathan Pryor 2012-10-03 16:30:22 UTC
Now what should be happening is that System.Object.6fe812e6-409e-4e73-af78-1fee4c29dcd3(IntPtr , IntPtr ) (the caller of IRunnableInvoker.n_Run(), which calls Runnable.Run()) should have a "catch" block which catches the RuntimeException thrown by Runnable.Run() and re-raises it on the Java side.

Since Java is in the middle of a JNI call, this should then be "re-raised" in JNIEnv.CallVoidMethod(), and since we're in a catch block the exception should be handled and we're fine.

That's not what's happening. :-(
Comment 2 Jonathan Pryor 2013-12-20 14:47:38 UTC
*** Bug 16903 has been marked as a duplicate of this bug. ***
Comment 3 Jonathan Pryor 2014-01-14 15:32:53 UTC
*** Bug 8900 has been marked as a duplicate of this bug. ***
Comment 7 Jeremy Kolb 2014-10-27 16:10:24 UTC
Any update on this?
Comment 10 Saurabh 2014-11-27 00:21:05 UTC
This is the screencast for the same: http://www.screencast.com/t/FmjL03CISgp
Comment 11 Jonathan Pryor 2014-12-04 15:42:40 UTC
@Saurabh:
> This is the screencast for the same: http://www.screencast.com/t/FmjL03CISgp

That doesn't show failure. That shows success.

From 1:01-1:05 the button is clicked three times. You refer to the Application output window, which shows a stack trace, but that's expected.

What's also expected *now*, but would not happen in 4.20, is that the app DOES NOT CRASH. It doesn't Exit. (The stack trace is NOT a sign of crashing.)

In particular, from Comment #0:

          try {
            IntPtr run = JNIEnv.GetMethodID (r.Class.Handle, "run", "()V");
            JNIEnv.CallVoidMethod(r.Handle, run);
            Console.WriteLine ("wtf?");
          } catch (Exception e) {
            var a = this.Application;
            Console.WriteLine ("Exception caught! {0}", e);
          }
        };

The entire point of the sample is that an exception is thrown, caught, and printed. You're seeing the message being printed, as you should.

What *was* happening is that the entire app would QUIT, dropping you back to the Home screen. That's not happening here.
Comment 12 Udham Singh 2015-04-20 08:50:39 UTC
I have checked this issue with the help of instructions and code provided in bug description and observed that this issue has been fixed. Hence I am closing this issue.

Screencast : http://www.screencast.com/t/sqPJZ8LWm

Environment Info : 

Mac OS X 10.9.5
Xamarin Studio 5.9 (build 431)
Mono 4.0.0 ((detached/c8db1b0)
GTK+ 2.24.23 (Raleigh theme)
Xcode 6.2 (6776)
Xamarin.Android 5.1.0.115 (Trial Edition)