Potentially all these IDisposable classes could be used after being
disposed, which would result in native crashes. We now do an explicit
check and throw an exception in managed land when the object has been
disposed.
This is particularly useful because:
a/ the native crashes are quite obscure, there no indication that
you're using a disposed object
b/ Gtk# is passing Context instances to user methods, and disposes them
when the method returns. So if the user code keeps a reference to the
Context, there a good chance it will try to use it after it's disposed.
Other changes in this patch include:
* Renaming a parameter to be more consistent with the other subsequent
ctor called.
* Replacing implementation of some [Obsolete()] methods with the call
to the methods they were replaced with, to avoid redundancy and the
need for more CheckDisposed() calls than necessary.
* Throw ArgumentException when receiving an IntPtr.Zero as a handle,
as a way to protect ourselves from wrapping invalid native pointers,
and throwing ObjectDisposedExceptions because the object was invalid in
the first place.
Signed-off-by: Bertrand Lorentz <bertrand.lorentz@gmail.com>
The sample writes the same PNG file over and over, with some pauses in
between iterations. Some indicative numbers are written to the console,
to help track performance and memory usage.
Feel free to add more elaborate drawing to this sample, to exercise more
of the cairo API.
A similar situation to what is described in commit e48ac63d54 also
happens with signal callbacks: some signals are passed a native object
that is wrapped in an IDisposable managed object, which is then passed
as an argument to the signal handler. We need to dispose those objects
when the signal handler is done.
Those parameters will now be disposed in a finally {...} block, after
the signal handler has returned. This means that handlers should not
keep a reference to such a parameter, as it will be disposed right after
they return.
This change only affects the Cairo.Context parameter of the Widget.Drawn
signal, but it was badly needed, as shown by the Pixbuf demo in the
GtkDemo sample, which was leaking tens of MBs of memory.
This way there's less redundancy, and if the library name changes in the
future, it will be changed only in one place.
Signed-off-by: Bertrand Lorentz <bertrand.lorentz@gmail.com>
Some virtual methods are passed a native object that is wrapped in an
IDisposable managed object, which is then passed on to the managed
overrides. We need to dispose those objects as soon as possible,
otherwise their native counterpart will not be freed until the next
garbage collection. Requiring the overrides to dispose them would be
cumbersome and error-prone.
Those parameters will now be disposed in a finally {...} block, after
the virtual method has returned. This means that overrides should not
keep a reference to such a parameter outside of the scope of the method,
as it will be diposed when the method returns.
This change only affects Cairo.Context parameter for now, but it was
particularly needed for them, as they could happily hold on to tens of
MBs of memory until the next garbage collection.
This reverts commit 21bfaa7a9d.
After fixing the memory leak when finalizing a Context object in the
previous commit, native crashes would happen when using a Gtk#-based
app. The reason is that this commit tried to fix the leak with the wrong
approach of marking the CairoContext as owned. This avoided the leak by
not incrementing the reference count, but now that the leak is fixed,
cairo_destroy is called one time too much.
The CairoContext passed in the Draw signal is not marked as
transfer-ownership=full in GObject-Introspection metadata. So unmarking
this as owned fixes the "potential double-free" assertion that was
causing the crash.
When the finalizer calls Dispose(), disposing is false, it means that
CairoDebug traces should be printed, but the reference count on the
native context should still be decreased. Otherwise a real leak
would appear, as the native context would never be freed when the
managed object is GCed.
This commit makes it possible to build any project of the gtk-sharp.sln
from an IDE (except audit and sample projects, which require a bit more
work).
This doesn't mean that autotools is deprecated, but just that it is more
comfortable to use an IDE when working on gtk-sharp because it will
offer better auto-completion, and will stop highlight misleading
semantic errors, from now on.
Clarify the README thanks to the use of pkg-config, and add a
configure-time warning so people notice about the problem without having
to read the README.
At application shutdown, it's very likely to be spammed by
gui-thread-check with a river of:
*** GTK CALL NOT IN GUI THREAD: Widget.Dispose
*** GTK CALL NOT IN GUI THREAD: Widget.remove_InternalDestroyed
*** GTK CALL NOT IN GUI THREAD: Widget.Dispose
*** GTK CALL NOT IN GUI THREAD: Widget.remove_InternalDestroyed
...
From what I gather, these two methods (in gtk-sharp master[1]) could
be called by the finalizers, but do not call any unmanaged functions,
so it should be ok to not report them as violations.
[1] https://github.com/mono/gtk-sharp/blob/master/gtk/Widget.cs
Cherry-picked from 77a40599ca
Using fflush() right away after printf() calls avoids the buffers to
be written in an apparently complete-out-of-sync way from the point
of view of the developer. This problem would specially occur when
redirecting all output to a file this way:
mono Foo.exe > out.txt 2>&1
Without this fix, all the output from gui-thread-check would appear
at the end of the file, instead of in between the output generated by
the program.
Cherry-picked from 6988cd4cd2
There are two elements repeated in this expression:
(( ((A) || (B)) || (B)) && C)
We can simplify "(A || B) || B" to simply "A || B",
so the result is a bit more readable this way:
(A || B) && C