Bug 49742 - NPE in EventListenerList (Concurrency)
Summary: NPE in EventListenerList (Concurrency)
Status: NEW
Alias: None
Product: Batik - Now in Jira
Classification: Unclassified
Component: SVG DOM (show other bugs)
Version: 1.7
Hardware: PC Windows XP
: P2 minor
Target Milestone: ---
Assignee: Batik Developer's Mailing list
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-08-12 06:45 UTC by Christoph Bimminger
Modified: 2010-08-12 06:45 UTC (History)
0 users



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Christoph Bimminger 2010-08-12 06:45:54 UTC
not repeatable, not clearly reproducable. bug occurs frequently in our Jemmy application GUI tests.

java.lang.NullPointerException
	at org.apache.batik.dom.events.EventListenerList.removeListener(EventListenerList.java:88)
	at org.apache.batik.dom.events.EventSupport.removeEventListenerNS(EventSupport.java:180)
	at org.apache.batik.dom.AbstractNode.removeEventListenerNS(AbstractNode.java:991)
	at org.apache.batik.dom.svg.SVGOMDocument.removeCSSNavigableDocumentListener(SVGOMDocument.java:473)
	at org.apache.batik.css.engine.CSSEngine.removeEventListeners(CSSEngine.java:487)
	at org.apache.batik.css.engine.CSSEngine.dispose(CSSEngine.java:516)
	at org.apache.batik.bridge.BridgeContext.removeDOMListeners(BridgeContext.java:1291)
	at org.apache.batik.bridge.BridgeContext.dispose(BridgeContext.java:1444)
	at org.apache.batik.swing.svg.AbstractJSVGComponent.installSVGDocument(AbstractJSVGComponent.java:721)
	at org.apache.batik.swing.JSVGCanvas.installSVGDocument(JSVGCanvas.java:591)
	at org.apache.batik.swing.svg.AbstractJSVGComponent$2.run(AbstractJSVGComponent.java:679)


I guess it's because we do call AbstractJSVGComponent's setSVGDocument frequently. I assume while one call of setSVGDocument still processes its installSVGDocument, another thread also tries to remove listeners. 

Code in EventListenerList, which causes NPE, is eht "else if" condition:

    else if (head != null
                && (namespaceURI != null && namespaceURI.equals(head.namespaceURI)
                    || namespaceURI == null && head.namespaceURI == null)
                && listener == head.listener) {
            head = head.next;
        }

The only reason for NPE that I can figure out is, that the member "head" in thread A passes the "head != null" condition, then thread B already processes head=head.next (what may set head = NULL), and then thread A resumes with accessing head.namecpaceURI or head.listener -> NPE.

What about assigning head to a local variable before entering the IF condition; and using the local variable for the conditions (and as source for assignment)?