From 2229cafc3833a017b3a107b4f6b207f0a95908f5 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Mon, 15 Feb 2010 12:04:50 +0000 Subject: [PATCH] stage: Add sanity checks for get_pending_swaps() The master clock might have a Stage during its destruction phase, without a StageWindow attached to it. If this happens and we try to dereference the StageWindow to get its class and call a virtual function we might experience some slight turbulence and... then... explode. http://bugzilla.openedhand.com/show_bug.cgi?id=1987 --- clutter/clutter-master-clock.c | 21 +++++++++++++-------- clutter/clutter-stage.c | 10 +++++++++- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/clutter/clutter-master-clock.c b/clutter/clutter-master-clock.c index 1e7efcf2d..8b4a42f95 100644 --- a/clutter/clutter-master-clock.c +++ b/clutter/clutter-master-clock.c @@ -129,11 +129,14 @@ master_clock_is_running (ClutterMasterClock *master_clock) /* If all of the stages are busy waiting for a swap-buffers to complete * then we stop the master clock... */ for (l = stages; l != NULL; l = l->next) - if (_clutter_stage_get_pending_swaps (l->data) == 0) - { - stage_free = TRUE; - break; - } + { + if (_clutter_stage_get_pending_swaps (l->data) == 0) + { + stage_free = TRUE; + break; + } + } + if (!stage_free) return FALSE; @@ -141,9 +144,11 @@ master_clock_is_running (ClutterMasterClock *master_clock) return TRUE; for (l = stages; l; l = l->next) - if (_clutter_stage_has_queued_events (l->data) || - _clutter_stage_needs_update (l->data)) - return TRUE; + { + if (_clutter_stage_has_queued_events (l->data) || + _clutter_stage_needs_update (l->data)) + return TRUE; + } if (master_clock->ensure_next_iteration) { diff --git a/clutter/clutter-stage.c b/clutter/clutter-stage.c index 738478c5b..00fb26c1a 100644 --- a/clutter/clutter-stage.c +++ b/clutter/clutter-stage.c @@ -2393,7 +2393,15 @@ clutter_stage_get_minimum_size (ClutterStage *stage, int _clutter_stage_get_pending_swaps (ClutterStage *stage) { - ClutterStageWindow *stage_window = _clutter_stage_get_window (stage); + ClutterStageWindow *stage_window; + + if (CLUTTER_PRIVATE_FLAGS (stage) & CLUTTER_ACTOR_IN_DESTRUCTION) + return 0; + + stage_window = _clutter_stage_get_window (stage); + if (stage_window == NULL) + return 0; + return _clutter_stage_window_get_pending_swaps (stage_window); }