2 using System
.Runtime
.InteropServices
;
3 using System
.Runtime
.CompilerServices
;
5 public class MonoPInvokeCallbackAttribute
: Attribute
{
6 public MonoPInvokeCallbackAttribute (Type delegateType
) { }
11 [DllImport ("libtest")]
12 public static extern void mono_test_setjmp_and_call (VoidVoidDelegate del
, out IntPtr handle
);
14 [DllImport ("libtest")]
15 public static extern void mono_test_setup_ftnptr_eh_callback (VoidVoidDelegate del
, VoidHandleHandleOutDelegate inside_eh_callback
);
17 [DllImport ("libtest")]
18 public static extern void mono_test_cleanup_ftptr_eh_callback ();
20 public delegate void VoidVoidDelegate ();
21 public delegate void VoidHandleHandleOutDelegate (uint handle
, out int exception_handle
);
23 public class SpecialExn
: Exception
{
26 public class SomeOtherExn
: Exception
{
29 [MethodImpl (MethodImplOptions
.NoInlining
)]
30 private static void callee (ref bool called
) {
32 throw new SpecialExn ();
36 public static bool called
;
37 public static bool finally_called
;
39 public static void Setup () {
41 finally_called
= false;
44 [MonoPInvokeCallback (typeof (VoidVoidDelegate
))]
45 public static void M1 () {
48 throw new Exception ("unexpected return from callee");
49 } catch (SomeOtherExn
) {
51 finally_called
= true;
55 [MonoPInvokeCallback (typeof (VoidVoidDelegate
))]
56 public static void M2 () {
59 throw new Exception ("unexpected return from callee");
60 } catch (SomeOtherExn
) {
65 public static int test_0_setjmp_exn_handler ()
69 VoidVoidDelegate f
= new VoidVoidDelegate (Caller
.M1
);
72 mono_test_setjmp_and_call (f
, out res
);
73 } catch (SpecialExn
) {
74 Console
.Error
.WriteLine ("should not have caught a SpecialExn");
78 Console
.Error
.WriteLine ("delegate not even called");
81 if (!Caller
.finally_called
) {
82 Console
.Error
.WriteLine ("finally not reached");
85 if (res
== IntPtr
.Zero
) {
86 Console
.Error
.WriteLine ("res should be a GCHandle, was 0");
89 GCHandle h
= GCHandle
.FromIntPtr (res
);
93 Console
.Error
.WriteLine ("GCHandle target was null");
96 else if (o
is SpecialExn
)
99 Console
.Error
.WriteLine ("o was not a SpecialExn, it is {0}", o
);
104 public class Caller2
{
105 public static bool rethrow_called
;
106 public static bool exception_caught
;
107 public static bool return_from_inner_managed_callback
;
109 public static void Setup () {
110 rethrow_called
= false;
111 exception_caught
= false;
112 return_from_inner_managed_callback
= false;
115 public static void RethrowException (uint original_exception
) {
116 var e
= (Exception
) GCHandle
.FromIntPtr ((IntPtr
) original_exception
).Target
;
117 rethrow_called
= true;
118 System
.Runtime
.ExceptionServices
.ExceptionDispatchInfo
.Capture (e
).Throw ();
121 [MonoPInvokeCallback (typeof (VoidHandleHandleOutDelegate
))]
122 public static void Del2 (uint original_exception
, out int exception_handle
) {
123 exception_handle
= 0;
125 RethrowException (original_exception
);
126 } catch (Exception ex
) {
127 var handle
= GCHandle
.Alloc (ex
, GCHandleType
.Normal
);
128 exception_handle
= GCHandle
.ToIntPtr (handle
).ToInt32 ();
129 exception_caught
= true;
131 return_from_inner_managed_callback
= true;
135 public static int test_0_throw_and_raise_exception ()
139 VoidVoidDelegate f
= new VoidVoidDelegate (Caller
.M2
);
140 VoidHandleHandleOutDelegate del2
= new VoidHandleHandleOutDelegate (Caller2
.Del2
);
141 bool outer_managed_callback
= false;
143 mono_test_setup_ftnptr_eh_callback (f
, del2
);
144 } catch (Exception e
) {
145 outer_managed_callback
= true;
148 if (!outer_managed_callback
) {
149 Console
.Error
.WriteLine ("outer managed callback did not throw exception");
152 if (!Caller2
.rethrow_called
) {
153 Console
.Error
.WriteLine ("exception was not rethrown by eh callback");
156 if (!Caller2
.exception_caught
) {
157 Console
.Error
.WriteLine ("rethrown exception was not caught");
160 if (!Caller2
.return_from_inner_managed_callback
) {
161 Console
.Error
.WriteLine ("managed callback called from native eh callback did not return");
165 mono_test_cleanup_ftptr_eh_callback ();
171 return TestDriver
.RunTests (typeof (Tests
));