2007-03-08 Mike Kestner <mkestner@novell.com>

* glib/*.cs : add try/catch blocks to native callback
	methods for DestroyNotify, Copy/Free, and ToggleNotify handlers.  
	Raise UnhandledException events on catches.  

svn path=/trunk/gtk-sharp/; revision=73965
This commit is contained in:
Mike Kestner 2007-03-08 20:28:24 +00:00
parent da407f8ed7
commit 57810954a3
10 changed files with 91 additions and 42 deletions

View File

@ -1,3 +1,9 @@
2007-03-08 Mike Kestner <mkestner@novell.com>
* glib/*.cs : add try/catch blocks to native callback
methods for DestroyNotify, Copy/Free, and ToggleNotify handlers.
Raise UnhandledException events on catches.
2007-03-06 Mike Kestner <mkestner@novell.com> 2007-03-06 Mike Kestner <mkestner@novell.com>
* generator/Signal.cs : add try/catch blocks to native callback * generator/Signal.cs : add try/catch blocks to native callback

View File

@ -96,10 +96,14 @@ namespace GLib {
// object that owned the native delegate wrapper no longer // object that owned the native delegate wrapper no longer
// exists and the instance of the delegate itself is removed from the hash table. // exists and the instance of the delegate itself is removed from the hash table.
private void OnDestroy (IntPtr data) { private void OnDestroy (IntPtr data) {
lock (typeof (DelegateWrapper)) { try {
if (instances.ContainsKey (this)) { lock (typeof (DelegateWrapper)) {
instances.Remove (this); if (instances.ContainsKey (this)) {
instances.Remove (this);
}
} }
} catch (Exception e) {
ExceptionManager.RaiseUnhandledException (e, false);
} }
} }
} }

View File

@ -55,6 +55,7 @@ namespace GLib {
Console.Error.WriteLine ("Exception in Gtk# callback delegate"); Console.Error.WriteLine ("Exception in Gtk# callback delegate");
Console.Error.WriteLine (" Note: Applications can use GLib.ExceptionManager.UnhandledException to handle the exception."); Console.Error.WriteLine (" Note: Applications can use GLib.ExceptionManager.UnhandledException to handle the exception.");
Console.Error.WriteLine (e); Console.Error.WriteLine (e);
Console.Error.WriteLine (new System.Diagnostics.StackTrace (true));
Environment.Exit (1); Environment.Exit (1);
} }

View File

@ -27,6 +27,7 @@ namespace GLib {
using System.Collections; using System.Collections;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
[CDeclCallback]
public delegate bool IdleHandler (); public delegate bool IdleHandler ();
public class Idle { public class Idle {
@ -40,12 +41,17 @@ namespace GLib {
public bool Handler () public bool Handler ()
{ {
IdleHandler idle_handler = (IdleHandler) real_handler; try {
IdleHandler idle_handler = (IdleHandler) real_handler;
bool cont = idle_handler (); bool cont = idle_handler ();
if (!cont) if (!cont)
Remove (); Remove ();
return cont; return cont;
} catch (Exception e) {
ExceptionManager.RaiseUnhandledException (e, false);
}
return false;
} }
} }

View File

@ -56,18 +56,28 @@ namespace GLib {
static IntPtr Copy (IntPtr ptr) static IntPtr Copy (IntPtr ptr)
{ {
if (ptr == IntPtr.Zero) try {
return ptr; if (ptr == IntPtr.Zero)
GCHandle gch = (GCHandle) ptr; return ptr;
return (IntPtr) GCHandle.Alloc (gch.Target); GCHandle gch = (GCHandle) ptr;
return (IntPtr) GCHandle.Alloc (gch.Target);
} catch (Exception e) {
ExceptionManager.RaiseUnhandledException (e, false);
}
return IntPtr.Zero;
} }
static void Free (IntPtr ptr) static void Free (IntPtr ptr)
{ {
if (ptr == IntPtr.Zero) try {
return; if (ptr == IntPtr.Zero)
GCHandle gch = (GCHandle) ptr; return;
gch.Free (); GCHandle gch = (GCHandle) ptr;
gch.Free ();
} catch (Exception e) {
ExceptionManager.RaiseUnhandledException (e, false);
}
} }
public static IntPtr WrapObject (object obj) public static IntPtr WrapObject (object obj)

View File

@ -347,15 +347,19 @@ namespace GLib {
void NotifyCallback (IntPtr handle, IntPtr pspec, IntPtr gch) void NotifyCallback (IntPtr handle, IntPtr pspec, IntPtr gch)
{ {
GLib.Signal sig = ((GCHandle) gch).Target as GLib.Signal; try {
if (sig == null) GLib.Signal sig = ((GCHandle) gch).Target as GLib.Signal;
throw new Exception("Unknown signal GC handle received " + gch); if (sig == null)
throw new Exception("Unknown signal GC handle received " + gch);
NotifyArgs args = new NotifyArgs (); NotifyArgs args = new NotifyArgs ();
args.Args = new object[1]; args.Args = new object[1];
args.Args[0] = pspec; args.Args[0] = pspec;
NotifyHandler handler = (NotifyHandler) sig.Handler; NotifyHandler handler = (NotifyHandler) sig.Handler;
handler (GLib.Object.GetObject (handle), args); handler (GLib.Object.GetObject (handle), args);
} catch (Exception e) {
ExceptionManager.RaiseUnhandledException (e, false);
}
} }
void ConnectNotification (string signal, NotifyHandler handler) void ConnectNotification (string signal, NotifyHandler handler)

View File

@ -56,11 +56,15 @@ namespace GLib {
delegate void SignalDestroyNotify (IntPtr data, IntPtr obj); delegate void SignalDestroyNotify (IntPtr data, IntPtr obj);
static void OnNativeDestroy (IntPtr data, IntPtr obj) static void OnNativeDestroy (IntPtr data, IntPtr obj)
{ {
GCHandle gch = (GCHandle) data; try {
Signal s = gch.Target as Signal; GCHandle gch = (GCHandle) data;
s.DisconnectHandler (s.before_id); Signal s = gch.Target as Signal;
s.DisconnectHandler (s.after_id); s.DisconnectHandler (s.before_id);
gch.Free (); s.DisconnectHandler (s.after_id);
gch.Free ();
} catch (Exception e) {
ExceptionManager.RaiseUnhandledException (e, false);
}
} }
private Signal (GLib.Object obj, string signal_name, Delegate marshaler) private Signal (GLib.Object obj, string signal_name, Delegate marshaler)

View File

@ -24,6 +24,7 @@ namespace GLib {
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
[CDeclCallback]
public delegate bool TimeoutHandler (); public delegate bool TimeoutHandler ();
public class Timeout { public class Timeout {
@ -37,12 +38,17 @@ namespace GLib {
public bool Handler () public bool Handler ()
{ {
TimeoutHandler timeout_handler = (TimeoutHandler) real_handler; try {
TimeoutHandler timeout_handler = (TimeoutHandler) real_handler;
bool cont = timeout_handler (); bool cont = timeout_handler ();
if (!cont) if (!cont)
Remove (); Remove ();
return cont; return cont;
} catch (Exception e) {
ExceptionManager.RaiseUnhandledException (e, false);
}
return false;
} }
} }

View File

@ -74,7 +74,7 @@ namespace GLib {
if (weak.IsAlive) if (weak.IsAlive)
reference = weak.Target; reference = weak.Target;
else else
throw new Exception ("Toggling dead object wrapper"); throw new Exception ("Toggling dead wrapper");
} }
} }
@ -83,9 +83,13 @@ namespace GLib {
static void RefToggled (IntPtr data, IntPtr handle, bool is_last_ref) static void RefToggled (IntPtr data, IntPtr handle, bool is_last_ref)
{ {
GCHandle gch = (GCHandle) data; try {
ToggleRef tref = gch.Target as ToggleRef; GCHandle gch = (GCHandle) data;
tref.Toggle (is_last_ref); ToggleRef tref = gch.Target as ToggleRef;
tref.Toggle (is_last_ref);
} catch (Exception e) {
ExceptionManager.RaiseUnhandledException (e, false);
}
} }
static ToggleNotifyHandler toggle_notify_callback; static ToggleNotifyHandler toggle_notify_callback;

View File

@ -34,10 +34,14 @@ namespace GLib {
delegate void DestroyNotify (IntPtr data); delegate void DestroyNotify (IntPtr data);
static void OnNativeDestroy (IntPtr data) static void OnNativeDestroy (IntPtr data)
{ {
GCHandle gch = (GCHandle) data; try {
WeakObject obj = gch.Target as WeakObject; GCHandle gch = (GCHandle) data;
obj.Dispose (); WeakObject obj = gch.Target as WeakObject;
gch.Free (); obj.Dispose ();
gch.Free ();
} catch (Exception e) {
ExceptionManager.RaiseUnhandledException (e, false);
}
} }
void Dispose () void Dispose ()