Bug 29620 - SVGStyledElement::getPresentationAttribute() can return a shared CSSValue (some SVG tests randomly fail on the bot, and in release builds)
Summary: SVGStyledElement::getPresentationAttribute() can return a shared CSSValue (so...
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: SVG (show other bugs)
Version: 528+ (Nightly build)
Hardware: Mac OS X 10.5
: P2 Normal
Assignee: Nobody
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-09-21 16:00 PDT by Simon Fraser (smfr)
Modified: 2010-12-15 13:35 PST (History)
9 users (show)

See Also:


Attachments
Speculative fix (1.69 KB, patch)
2009-10-27 13:50 PDT, Eric Seidel (no email)
no flags Details | Formatted Diff | Diff
Cunning test case. (402 bytes, image/svg+xml)
2009-10-27 14:04 PDT, Eric Seidel (no email)
no flags Details
Patch v1 (4.99 KB, patch)
2009-10-27 14:25 PDT, Eric Seidel (no email)
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Simon Fraser (smfr) 2009-09-21 16:00:47 PDT
A subset of SVG tests fail randomly on the build bots:

http://build.webkit.org/results/Leopard%20Intel%20Release%20(Tests)/r48598%20(5194)/results.html

The ones that fail are usually:

svg/custom/group-opacity.svg
svg/custom/image-with-aspect-ratio-stretch.svg
svg/custom/inner-percent.svg
svg/custom/invalid-css.svg
svg/custom/invalid-fill-hex.svg
svg/custom/invalid-fill.svg

In every case, the failure is a red->green color difference:
[color=#FF0000] -> [color=#008000]
Comment 1 Eric Seidel (no email) 2009-09-21 16:05:18 PDT
I could have sworn we had a bug about this already, but searching just now I don't see one.  Mark would know.

I think we should just skip them.  IIRC Mark did some investigation on the bot and was unable to find a cause.  I've never seen them fail locally, but failing on the bot is nearly as bad as tools which depend on the tree state will get false-failures.
Comment 2 Simon Fraser (smfr) 2009-09-21 16:08:27 PDT
This seems like a genuine bug; I don't think we should just skip them. I can reproduce this locally with a few iterations of the tests and a release build.
Comment 3 Mark Rowe (bdash) 2009-09-21 16:12:08 PDT
I'm certain that we had a bug about this too but couldn't find it when looking.  The failures are in no way specific to the bots so they're definitely worth investigating before being skipped.
Comment 4 Mark Rowe (bdash) 2009-09-21 16:13:01 PDT
Bug 26219.
Comment 5 Simon Fraser (smfr) 2009-09-22 10:55:20 PDT
The difference in the test result stems from a behavioral fork in StyledElement::attributeChanged() when parsing the 'fill' attribute. When the test succeeds, the call to getMappedAttributeDecl() returns null. When it fails, getMappedAttributeDecl() returns something (from an earlier test?).
Comment 6 Simon Fraser (smfr) 2009-09-22 16:52:59 PDT
The mysterious green is coming from fill-SVGPaint-interface.svg, which does this:

        var fill = rect.getPresentationAttribute('fill');
        fill.setRGBColor("green");

This is touching a CSSMappedAttributeDeclaration which is in the mapped attribute cache. That's bad.
Comment 7 Simon Fraser (smfr) 2009-09-22 17:04:46 PDT
Bug 18512 was supposed to fix this?
Comment 8 Simon Fraser (smfr) 2009-09-22 17:13:16 PDT
When it fails it's not hitting the !cssSVGAttr->style()->hasOneRef() case.
Comment 9 Eric Seidel (no email) 2009-09-23 11:07:10 PDT
A huge thank you to simon for the investigation!
Comment 10 Eric Seidel (no email) 2009-10-27 08:55:11 PDT
Sigh.  This started occurring much more frequently on the bots as of yesterday.  I'll try to find time today to look more.
Comment 11 Eric Seidel (no email) 2009-10-27 12:04:47 PDT
http://trac.webkit.org/browser/trunk/WebCore/svg/SVGStyledElement.cpp#L243

is the code in question.  Note there is already a FIXME there:
    // FIXME: Is it possible that the style will not be shared at the time this
    // is called, but a later addition to the DOM will make it shared?
    if (!cssSVGAttr->style()->hasOneRef()) {
        cssSVGAttr->setDecl(0);
        int propId = SVGStyledElement::cssPropertyIdForSVGAttributeName(cssSVGAttr->name());
        addCSSProperty(cssSVGAttr, propId, cssSVGAttr->value());
    }
Comment 12 Eric Seidel (no email) 2009-10-27 12:07:22 PDT
http://www.w3.org/TR/SVG/types.html#InterfaceSVGStylable
is the spec definition of getPresentationAttribute:

getPresentationAttribute
Returns the base (i.e., static) value of a given presentation attribute as an object of type CSSValue. The returned object is live; changes to the objects represent immediate changes to the objects to which the CSSValue is attached.

I'm not sure exactly what to do here, but I'll make an attempt and then ask Hyatt.
Comment 13 Eric Seidel (no email) 2009-10-27 12:35:38 PDT
I still don't understand what's getting shared here.  MappedAttribute?  CSSValue?  MappedAttributeDecl?  What is surviving between tests and being re-used here?

Some mapping of green -> a color value I think.  I'm just not sure which class is storing that.
Comment 14 Simon Fraser (smfr) 2009-10-27 12:52:23 PDT
The shared object is a CSSMappedAttributeDeclaration, which is pointed to by the MappedAttribute. The CSSMappedAttributeDeclaration lives in the cache (mappedAttributeDecls) managed by StyledElement.

CSSMappedAttributeDeclaration  is a CSSStyleDeclaration, which returns a reference to a live CSSValue via getPropertyCSSValue().
Comment 15 Eric Seidel (no email) 2009-10-27 13:50:36 PDT
Created attachment 41979 [details]
Speculative fix
Comment 16 Eric Seidel (no email) 2009-10-27 13:52:10 PDT
Do I need to call:
        setNeedsStyleRecalc();
or
        if (namedAttrMap)
            mappedAttributes()->declRemoved();
?

Grepping through the source code for setDecl(0) yields conflicting examples.  I'm not really sure when declRemoved() and declAdded() should be called.  I think those functions probably need clearer names.
Comment 17 Eric Seidel (no email) 2009-10-27 13:53:37 PDT
Do you have recommended steps for me to reproduce this locally?  Ideally we would come up with a test which always failed due to this.  I'm not sure I yet fully understand what's going on enough to create one.
Comment 18 Simon Fraser (smfr) 2009-10-27 13:58:14 PDT
I was able to reproduce this reliably by paring down the tests in svg/custom, but keeping fill-SVGPaint-interface.svg and the tests listed in comment 1.

I'm not sure you can test this in a single test, unless you do something cunning with JS to stuff the cache, then mutate the value, then re-use that cached attribute.
Comment 19 Eric Seidel (no email) 2009-10-27 14:04:45 PDT
Created attachment 41982 [details]
Cunning test case.

I am cunning.  Here is a 100% reproducible case.  I'll make sure my fix fixes it.
Comment 20 Eric Seidel (no email) 2009-10-27 14:25:16 PDT
Created attachment 41988 [details]
Patch v1
Comment 21 Nikolas Zimmermann 2009-10-27 14:27:28 PDT
Comment on attachment 41988 [details]
Patch v1

Oh that simple testcase exposes the bug? It makes me cry :(
r=me, looks sane.
Comment 22 Eric Seidel (no email) 2009-10-27 14:36:05 PDT
Simon said this looked good to him too, so I"ll land this and email hyatt so that he sees this go by.
Comment 23 WebKit Commit Bot 2009-10-27 17:18:22 PDT
Comment on attachment 41988 [details]
Patch v1

Clearing flags on attachment: 41988

Committed r50185: <http://trac.webkit.org/changeset/50185>
Comment 24 WebKit Commit Bot 2009-10-27 17:18:27 PDT
All reviewed patches have been landed.  Closing bug.