From aa3365e7a2c4de405dab8ecc27283b3a64935dcf Mon Sep 17 00:00:00 2001 From: Robin Haberkorn Date: Mon, 1 Feb 2016 09:36:30 +0100 Subject: 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. --- gtk/ScintillaGTK.cxx | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/gtk/ScintillaGTK.cxx b/gtk/ScintillaGTK.cxx index 25e160510..792dd3e22 100644 --- a/gtk/ScintillaGTK.cxx +++ b/gtk/ScintillaGTK.cxx @@ -20,6 +20,7 @@ #include #include #include +#include #include #if defined(__WIN32__) || defined(_MSC_VER) @@ -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(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( - 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 @@ -2939,9 +2940,6 @@ gboolean ScintillaGTK::IdleCallback(gpointer pSci) { ScintillaGTK *sciThis = static_cast(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 @@ -2949,21 +2947,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(pSci); sciThis->IdleWork(); -#ifndef GDK_VERSION_3_6 - gdk_threads_leave(); -#endif // Idler will be automatically stopped return FALSE; } @@ -2973,7 +2962,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); } } -- cgit v1.2.3