aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorColomban Wendling <ban@herbesfolles.org>2016-05-11 23:00:37 +0200
committerColomban Wendling <ban@herbesfolles.org>2016-05-11 23:00:37 +0200
commit3f7b52da84cf6a8168c555bddbe1e8919cee1334 (patch)
treedbf5a98311dfd4d011241e15fa84191e4ede60ea
parent9b3c2f67fb36e4d29f375475c35ed1489edb925d (diff)
downloadscintilla-mirror-3f7b52da84cf6a8168c555bddbe1e8919cee1334.tar.gz
Bug [#1827]. GTK: Avoid possible IdleWork() calls on destructed objects
The idle callback removal clause in the ScintillaGTK destructor got broken in 4e5c321dda8e69104cb7b639c3107dc11dbc00f6, leading to the callback not being removed thus possibly running after the instance destruction. Indeed, gdk_threads_add_idle() wraps g_idle_add() with a custom user data, thus making the g_source_remove_by_user_data() call in the destructor incorrect, as we give it our own user data, not GDK's wrapper one. Fix the callback removal not to use user data matching to avoid this.
-rw-r--r--gtk/ScintillaGTK.cxx21
-rw-r--r--src/Editor.h4
2 files changed, 17 insertions, 8 deletions
diff --git a/gtk/ScintillaGTK.cxx b/gtk/ScintillaGTK.cxx
index 10514eece..9fc8e4cc4 100644
--- a/gtk/ScintillaGTK.cxx
+++ b/gtk/ScintillaGTK.cxx
@@ -167,6 +167,8 @@ class ScintillaGTK : public ScintillaBase {
#endif
bool repaintFullWindow;
+ guint styleIdleID;
+
// Private so ScintillaGTK objects can not be copied
ScintillaGTK(const ScintillaGTK &);
ScintillaGTK &operator=(const ScintillaGTK &);
@@ -325,6 +327,7 @@ private:
static gboolean TimeOut(gpointer ptt);
static gboolean IdleCallback(gpointer pSci);
static gboolean StyleIdle(gpointer pSci);
+ virtual void IdleWork();
virtual void QueueIdleWork(WorkNeeded::workItems items, int upTo);
static void PopUpCB(GtkMenuItem *menuItem, ScintillaGTK *sciThis);
@@ -392,7 +395,8 @@ ScintillaGTK::ScintillaGTK(_ScintillaObject *sci_) :
lastWheelMouseDirection(0),
wheelMouseIntensity(0),
rgnUpdate(0),
- repaintFullWindow(false) {
+ repaintFullWindow(false),
+ styleIdleID(0) {
sci = sci_;
wMain = GTK_WIDGET(sci);
@@ -424,7 +428,10 @@ ScintillaGTK::ScintillaGTK(_ScintillaObject *sci_) :
}
ScintillaGTK::~ScintillaGTK() {
- g_source_remove_by_user_data(this);
+ if (styleIdleID) {
+ g_source_remove(styleIdleID);
+ styleIdleID = 0;
+ }
if (evbtn) {
gdk_event_free(reinterpret_cast<GdkEvent *>(evbtn));
evbtn = 0;
@@ -2966,12 +2973,16 @@ gboolean ScintillaGTK::StyleIdle(gpointer pSci) {
return FALSE;
}
+void ScintillaGTK::IdleWork() {
+ Editor::IdleWork();
+ styleIdleID = 0;
+}
+
void ScintillaGTK::QueueIdleWork(WorkNeeded::workItems items, int upTo) {
Editor::QueueIdleWork(items, upTo);
- if (!workNeeded.active) {
+ if (!styleIdleID) {
// Only allow one style needed to be queued
- workNeeded.active = true;
- gdk_threads_add_idle_full(G_PRIORITY_HIGH_IDLE, StyleIdle, this, NULL);
+ styleIdleID = gdk_threads_add_idle_full(G_PRIORITY_HIGH_IDLE, StyleIdle, this, NULL);
}
}
diff --git a/src/Editor.h b/src/Editor.h
index 9cc648e84..c1545d34b 100644
--- a/src/Editor.h
+++ b/src/Editor.h
@@ -46,13 +46,11 @@ public:
workStyle=1,
workUpdateUI=2
};
- bool active;
enum workItems items;
Position upTo;
- WorkNeeded() : active(false), items(workNone), upTo(0) {}
+ WorkNeeded() : items(workNone), upTo(0) {}
void Reset() {
- active = false;
items = workNone;
upTo = 0;
}