diff options
| author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2016-04-08 09:25:05 +1000 | 
|---|---|---|
| committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2016-04-08 09:25:05 +1000 | 
| commit | 68a2a44587388528e344dc25a1a33e0e17e7e468 (patch) | |
| tree | 231f119bbb4006ceaedc97923f245f53d85a9a4b | |
| parent | 0604389a02a2cb5f33f5f84e460ad3d7a55f1fc4 (diff) | |
| download | scintilla-mirror-68a2a44587388528e344dc25a1a33e0e17e7e468.tar.gz | |
Scintilla Gtk: use gdk_threads_add_idle_full() instead of g_idle_add_full() and gdk_threads_add_timeout() instead of g_timeout_add()
 * The g_idle/g_timeout watchers are not executed with the Gdk lock
   held. This causes memory corruptions and crashes when accessing
   the Scintilla object from the non-main-loop-thread.
   At least this was the case after Gdk 3.6 since Scintilla
   used gdk_threads_enter()/leave() for earlier versions.
   The timeout handlers have possibly always been broken.
 * The new version should work with non-deprecated APIs in all Gdk
   versions.
 * Even though this only fixes the idle handlers in Gdk >= 3.6 where
   gdk_threads_enter() is deprecated (the only way to provoke
   above situation) - and the timers of course - this patch makes
   the code more elegant.
| -rw-r--r-- | gtk/ScintillaGTK.cxx | 21 | 
1 files changed, 5 insertions, 16 deletions
diff --git a/gtk/ScintillaGTK.cxx b/gtk/ScintillaGTK.cxx index ad9aa6568..80217660b 100644 --- a/gtk/ScintillaGTK.cxx +++ b/gtk/ScintillaGTK.cxx @@ -19,6 +19,7 @@  #include <glib.h>  #include <gmodule.h> +#include <gdk/gdk.h>  #include <gtk/gtk.h>  #include <gdk/gdkkeysyms.h> @@ -423,7 +424,7 @@ ScintillaGTK::ScintillaGTK(_ScintillaObject *sci_) :  }  ScintillaGTK::~ScintillaGTK() { -	g_idle_remove_by_data(this); +	g_source_remove_by_user_data(this);  	if (evbtn) {  		gdk_event_free(reinterpret_cast<GdkEvent *>(evbtn));  		evbtn = 0; @@ -1077,7 +1078,7 @@ bool ScintillaGTK::FineTickerRunning(TickReason reason) {  void ScintillaGTK::FineTickerStart(TickReason reason, int millis, int /* tolerance */) {  	FineTickerCancel(reason); -	timers[reason].timer = g_timeout_add(millis, TimeOut, &timers[reason]); +	timers[reason].timer = gdk_threads_add_timeout(millis, TimeOut, &timers[reason]);  }  void ScintillaGTK::FineTickerCancel(TickReason reason) { @@ -1093,7 +1094,7 @@ bool ScintillaGTK::SetIdle(bool on) {  		if (!idler.state) {  			idler.state = true;  			idler.idlerID = reinterpret_cast<IdlerID>( -				g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, IdleCallback, this, NULL)); +				gdk_threads_add_idle_full(G_PRIORITY_DEFAULT_IDLE, IdleCallback, this, NULL));  		}  	} else {  		// Stop idler, if it's running @@ -2937,9 +2938,6 @@ gboolean ScintillaGTK::IdleCallback(gpointer pSci) {  	ScintillaGTK *sciThis = static_cast<ScintillaGTK *>(pSci);  	// Idler will be automatically stopped, if there is nothing  	// to do while idle. -#ifndef GDK_VERSION_3_6 -	gdk_threads_enter(); -#endif  	bool ret = sciThis->Idle();  	if (ret == false) {  		// FIXME: This will remove the idler from GTK, we don't want to @@ -2947,21 +2945,12 @@ gboolean ScintillaGTK::IdleCallback(gpointer pSci) {  		// returns false (although, it should be harmless).  		sciThis->SetIdle(false);  	} -#ifndef GDK_VERSION_3_6 -	gdk_threads_leave(); -#endif  	return ret;  }  gboolean ScintillaGTK::StyleIdle(gpointer pSci) { -#ifndef GDK_VERSION_3_6 -	gdk_threads_enter(); -#endif  	ScintillaGTK *sciThis = static_cast<ScintillaGTK *>(pSci);  	sciThis->IdleWork(); -#ifndef GDK_VERSION_3_6 -	gdk_threads_leave(); -#endif  	// Idler will be automatically stopped  	return FALSE;  } @@ -2971,7 +2960,7 @@ void ScintillaGTK::QueueIdleWork(WorkNeeded::workItems items, int upTo) {  	if (!workNeeded.active) {  		// Only allow one style needed to be queued  		workNeeded.active = true; -		g_idle_add_full(G_PRIORITY_HIGH_IDLE, StyleIdle, this, NULL); +		gdk_threads_add_idle_full(G_PRIORITY_HIGH_IDLE, StyleIdle, this, NULL);  	}  }  | 
