summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSam Spilsbury <sam.spilsbury@canonical.com>2010-11-27 01:47:39 +0800
committerSam Spilsbury <sam.spilsbury@canonical.com>2010-11-27 01:47:39 +0800
commit3e1c09f13eb99af88bf0bd8d73be8bbcf533ded7 (patch)
tree9e8668df5f9db8482ce615aeafebdc370a92ac60 /src
parent2c5f1357520ef443fbfe464776cc46ebfcd47cb3 (diff)
downloadcompiz-with-glib-mainloop-3e1c09f13eb99af88bf0bd8d73be8bbcf533ded7.tar.gz
compiz-with-glib-mainloop-3e1c09f13eb99af88bf0bd8d73be8bbcf533ded7.tar.bz2
Detect when glib is being stupid and calls ::internalCallback even though we asked for the source to be removed (prevents access to free'd memory once we delete a CompTimer)
Diffstat (limited to 'src')
-rw-r--r--src/privatescreen.h2
-rw-r--r--src/screen.cpp27
2 files changed, 23 insertions, 6 deletions
diff --git a/src/privatescreen.h b/src/privatescreen.h
index ad95351..436556d 100644
--- a/src/privatescreen.h
+++ b/src/privatescreen.h
@@ -338,7 +338,7 @@ class PrivateScreen : public CoreOptions {
CompFileWatchList fileWatch;
CompFileWatchHandle lastFileWatchHandle;
- std::list<CompTimer *> timers;
+ std::list <int> removedTimers;
struct timeval lastTimeout;
std::list<CompWatchFd *> watchFds;
diff --git a/src/screen.cpp b/src/screen.cpp
index 931b90e..5bb405f 100644
--- a/src/screen.cpp
+++ b/src/screen.cpp
@@ -245,10 +245,23 @@ CompScreen::getFileWatches () const
/* TODO: move this code to timer.cpp */
bool
-CompTimer::internalCallback ()
+CompTimer::internalCallback (unsigned int id)
{
bool result;
+ /* Detect when the timer is still going and the internal
+ * object has been freed */
+ if (!screen->priv->removedTimers.empty ())
+ {
+ if (std::find (screen->priv->removedTimers.begin (),
+ screen->priv->removedTimers.end (),
+ id) != screen->priv->removedTimers.end ())
+ {
+ screen->priv->removedTimers.remove (id);
+ return false;
+ }
+ }
+
if (!mActive)
return false;
@@ -278,17 +291,20 @@ CompTimer::internalCallback ()
void
PrivateScreen::addTimer (CompTimer *timer)
{
+ unsigned int time = timer->mMinTime;
+ unsigned int id;
+
if (timer->mSource)
return;
- unsigned int time = timer->mMinTime;
-
timer->mSource = Glib::TimeoutSource::create (time);
if (timer->mSource)
{
timer->mSource->attach (priv->ctx);
- timer->mSource->connect (sigc::mem_fun <bool, CompTimer> (timer, &CompTimer::internalCallback));
+ id = g_source_get_id (timer->mSource->gobj ());
+ removedTimers.remove (id);
+ timer->mSource->connect (sigc::bind <unsigned int>(sigc::mem_fun (timer, &CompTimer::internalCallback), id));
timer->tick ();
}
else
@@ -304,6 +320,8 @@ PrivateScreen::removeTimer (CompTimer *timer)
if (timer->mExecuting)
timer->mForceFail = true;
+ removedTimers.push_back (g_source_get_id (timer->mSource->gobj ()));
+
timer->mSource.reset (); /* This will NULL the pointer */
}
@@ -4561,7 +4579,6 @@ PrivateScreen::PrivateScreen (CompScreen *screen) :
priv (this),
fileWatch (0),
lastFileWatchHandle (1),
- timers (0),
watchFds (0),
lastWatchFdHandle (1),
watchPollFds (0),