After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 670647 - workspace: avoid crash when selecting a zoomed clone
workspace: avoid crash when selecting a zoomed clone
Status: RESOLVED FIXED
Product: gnome-shell
Classification: Core
Component: general
unspecified
Other All
: Normal normal
: ---
Assigned To: gnome-shell-maint
gnome-shell-maint
: 671102 671733 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2012-02-22 22:52 UTC by Stefano Facchini
Modified: 2012-03-09 22:27 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
workspace: avoid crash when selecting a zoomed clone (1.24 KB, patch)
2012-02-22 22:52 UTC, Stefano Facchini
accepted-commit_now Details | Review
actor: Do not check for child destruction in add_child_internal() (5.59 KB, patch)
2012-02-28 15:49 UTC, Emmanuele Bassi (:ebassi)
none Details | Review

Description Stefano Facchini 2012-02-22 22:52:14 UTC
See patch.

It worked before because lower() and raise() were just reordering
in a list, but in post-apocalyptic Clutter they are two-step operations
i.e. "remove child" and "add child at position". Clearly the second
step fails for actors in destruction.
Comment 1 Stefano Facchini 2012-02-22 22:52:18 UTC
Created attachment 208222 [details] [review]
workspace: avoid crash when selecting a zoomed clone

The lightbox destroying method tries to call lower() for the
highlighted actor. Since the actor is currently in destruction,
the call to lower() fails and leaves the actor in an unstable state
which in the end causes a crash.

Fix this by retarding the lightbox destruction.
Comment 2 Florian Müllner 2012-02-23 00:21:25 UTC
Review of attachment 208222 [details] [review]:

Looks good. (I'd s/retard/delay/ in the commit message, but up to you)
Comment 3 Jasper St. Pierre (not reading bugmail) 2012-02-23 00:33:11 UTC
Review of attachment 208222 [details] [review]:

No, I don't think this is the right solution. Calling lower() shouldn't put the actor into an unstable state if it's in destruction. The promise from ebassi was that there would be no regressions from before the apocalypse, so I think it's safe to ask him to hold his promise.

(Leaving it at ACN, though... if we do eventually decide this is the right solution, please change 'retard')
Comment 4 Emmanuele Bassi (:ebassi) 2012-02-28 15:07:50 UTC
what is the problem, here? the bug report is not really clear on that.

I agree that there shouldn't be regressions (except when depending on undefined behaviour), but I'd like to understand what did break before I try and fix it.
Comment 5 Emmanuele Bassi (:ebassi) 2012-02-28 15:49:01 UTC
Created attachment 208596 [details] [review]
actor: Do not check for child destruction in add_child_internal()

We currently check for the IN_DESTRUCTION flag inside the
add_child_internal() function.

This check disallows calling methods that change the stacking order
within the destruction sequence, by triggering a critical warning first,
and leaving the actor in an undefined state, which then ends up being
caught by an assertion.

The reproducible sequence is:

  - actor gets destroyed;
  - another actor, linked to the first, will try to change the
    stacking order of the first actor;
  - changing the stacking order is a composite operation composed
    by the following steps:
    1. ref() the child;
    2. remove_child_internal(), which removes the reference;
    3. add_child_internal(), which adds a reference;
  - the state of the actor is not changed between (2) and (3), as
    it could be an expensive recomputation;
  - if (3) bails out, then the actor is in an undefined state, but
    still alive;
  - the destruction sequence terminates, but the actor is unparented
    while its state indicates being parented instead.
  - assertion failure.

The obvious fix would be to decompose each set_child_*_sibling() method
into proper remove_child()/add_child(), with state validation; this may
cause excessive work, though, and trigger a cascade of other bugs in
code that assumes that a change in the stacking order is an atomic
operation.

Another potential fix is to just remove this check here, and let code
doing stacking order changes inside the destruction sequence of an actor
continue doing the work.

The third fix is to silently bail out early from every
set_child_*_sibling() and set_child_at_index() method, and avoid doing
work.

I have a preference for the second solution, since it involves the least
amount of work, and the least amount of code duplication.

See bug:
Comment 6 Emmanuele Bassi (:ebassi) 2012-02-28 17:35:25 UTC
I'd like somebody to test the change in attachment 208596 [details] [review] and see if the assertion failure goes away; if it doesn't, I start making every method that changes the stacking order silently bail out if the child is inside its destruction sequence.
Comment 7 Stefano Facchini 2012-02-28 18:03:48 UTC
(In reply to comment #6)
> I'd like somebody to test the change in attachment 208596 [details] [review] and see if the
> assertion failure goes away;

This works for me.
Comment 8 Stefano Facchini 2012-02-29 22:07:54 UTC
attachment 208596 [details] [review] has been pushed, closing as FIXED
Comment 9 Jasper St. Pierre (not reading bugmail) 2012-03-01 05:37:01 UTC
*** Bug 671102 has been marked as a duplicate of this bug. ***
Comment 10 Florian Müllner 2012-03-09 22:27:19 UTC
*** Bug 671733 has been marked as a duplicate of this bug. ***