GException improvements with multithreading

Read all GError fields in GException constructor and free GError memory.

Quote from gtksharp2 fix: The original impl did not take into account exceptions marshalling across thread boundaries so it could end up with the error being accessed after being disposed.
This commit is contained in:
dmg 2021-04-01 19:46:39 +03:00 committed by Harry
parent bfcf29b070
commit 94ea7051f9

View file

@ -26,11 +26,15 @@ namespace GLib {
public class GException : Exception public class GException : Exception
{ {
IntPtr errptr; string msg;
public GException (IntPtr errptr) : base () public GException (IntPtr errptr)
{ {
this.errptr = errptr; var err = (GError)Marshal.PtrToStructure(errptr, typeof(GError));
Domain = err.Domain;
Code = err.Code;
msg = Marshaller.Utf8PtrToString(err.Msg);
g_clear_error(ref errptr);
} }
struct GError { struct GError {
@ -39,34 +43,14 @@ namespace GLib {
public IntPtr Msg; public IntPtr Msg;
} }
public int Code { public int Code { get; private set; }
get {
GError err = (GError) Marshal.PtrToStructure (errptr, typeof (GError));
return err.Code;
}
}
public int Domain { public int Domain { get; private set; }
get {
GError err = (GError) Marshal.PtrToStructure (errptr, typeof (GError)); public override string Message => msg;
return err.Domain;
}
}
public override string Message {
get {
GError err = (GError) Marshal.PtrToStructure (errptr, typeof (GError));
return Marshaller.Utf8PtrToString (err.Msg);
}
}
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate void d_g_clear_error(ref IntPtr errptr); delegate void d_g_clear_error(ref IntPtr errptr);
static d_g_clear_error g_clear_error = FuncLoader.LoadFunction<d_g_clear_error>(FuncLoader.GetProcAddress(GLibrary.Load(Library.GLib), "g_clear_error")); static d_g_clear_error g_clear_error = FuncLoader.LoadFunction<d_g_clear_error>(FuncLoader.GetProcAddress(GLibrary.Load(Library.GLib), "g_clear_error"));
~GException ()
{
g_clear_error (ref errptr);
} }
} }
}