From 68a2a44587388528e344dc25a1a33e0e17e7e468 Mon Sep 17 00:00:00 2001 From: Robin Haberkorn Date: Fri, 8 Apr 2016 09:25:05 +1000 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 ad9aa6568..80217660b 100644 --- a/gtk/ScintillaGTK.cxx +++ b/gtk/ScintillaGTK.cxx @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -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 @@ -2937,9 +2938,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 @@ -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(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); } } -- cgit v1.2.3