Closed Bug 445910 Opened 18 years ago Closed 18 years ago

use XPCOM cycle collector in accessibility classes

Categories

(Core :: Disability Access APIs, defect)

defect
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla1.9.1a2

People

(Reporter: surkov, Assigned: surkov)

References

Details

Attachments

(1 file, 4 obsolete files)

use XPCOM cycle collector in accessibility classes
Attached patch wip (obsolete) — Splinter Review
Does this fix our leak bugs, like bug 434491, bug 420068 or bug 443675?
Shortly what I wanted to do: we have an accessible tree, every accessible object of the tree holds pointers to parent, next sibling and first child accessible objects. Currently parent is nsCOMPtr, nextSibling and firstChild are raw pointers. I wanted to make to use nsCOMPtr for nextSibling and fisrtChild as well. Therefore I thought XPCOM cycle collector should helps here. But when I use nsCOMPtr for nextSibling and firstChild pointers and add them into traverse and unlink marcros then firefox hangs and then crashes. If I don't put nextSibling and firstChild into traverse and unlink macros then it works. Please look at the patch. Do you have any idea what's wrong? Does cycle collector work with objects that holds nsCOMPtr pointers for each other?
(In reply to comment #2) > Does this fix our leak bugs, like bug 434491, bug 420068 or bug 443675? > I think it fix nothing now :). Because we should turn raw pointers into nsCOMPtr. I'm not sure whether it helps with memory leaks but it should kill our crashes.
Actually I can't find any documentation about cycle collector (excepting probably http://developer.mozilla.org/en/docs/Interfacing_with_the_XPCOM_cycle_collector). And I can't find in mozilla sources our case.
Possibly traversing should move forward only, for example, down through the children? And when I added traversing through parent and children then I locked the circle?
traversing to next sibling and firsrt child doesn't help (firefox hangs and crashed then)
Comment on attachment 330210 [details] [diff] [review] wip (traverse next sibling and first child only, doesn't work) Random comments... >+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsAccessNode) >+ NS_INTERFACE_MAP_ENTRY(nsIAccessNode) >+ NS_INTERFACE_MAP_ENTRY(nsPIAccessNode) Should you add NS_INTERFACE_MAP_ENTRY(nsISupports) or maybe NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIAccessNode) ? >+NS_IMPL_CYCLE_COLLECTION_CLASS(nsAccessible) >+ >+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsAccessible, nsAccessNode) >+// NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParent) Why commented out? Who is keeping nsAccessible alive and when is nsAccessible released?
Attached patch wip3 (obsolete) — Splinter Review
(In reply to comment #8) > >+NS_IMPL_CYCLE_COLLECTION_CLASS(nsAccessible) > >+ > >+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsAccessible, nsAccessNode) > >+// NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParent) > Why commented out? I thought that may be a problem (traversing up and down). I fixed that in wip3 patch > Who is keeping nsAccessible alive and when is nsAccessible released? > 1) they keep each other by mParent, mNextSibling, mFirstChild 2) nsAccessNodeHashtable nsDocAccessible::mAccessNodeCache - cashe of all accessibles that belongs to the document 3) nsCOMArray<nsIAccessibleEvent> nsDocAccessible::mEventsToFire - technically accessibles object may be hold by nsIAccessibleEvent but it shouldn't happen 4) for example, in windows accessible objects may be used by screen readers via COM But why does it hang even if I don't process here all cases? I thought it may lead to memory leaks only.
There's plenty of ways to crash, for example your code might not be able to deal with the null members after unlinking. Another example, how are you dealing with mNextSibling == DEAD_END_ACCESSIBLE? I suggest you first get some more details about the crashes.
Thanks, Pete. You're right the problem is in DEAD_END_ACCESSIBLE
Attached patch patch (obsolete) — Splinter Review
Marco, could you try the patch?
Attachment #330203 - Attachment is obsolete: true
Attachment #330210 - Attachment is obsolete: true
Attachment #330219 - Attachment is obsolete: true
Attachment #330235 - Flags: review?(marco.zehe)
So far, except for one thing, I haven't seen anything bad. No crashes or anything like that. The one thing I did observe was this. With JAWS running: 1. Visit http://www.mozilla.org. 2. Press CTRL+L to go to Location bar. 3. Type in about:blank and hit enter. There was an instance where JAWS would not, for the life of it, let go of its previous document. So even when Firefox was showing a blank document, JAWS's virtual buffer still showed the Mozilla Foundation homepage. Later, I could not reproduce this, and I also could not reproduce using NVDA. Regarding bug 429030: There is a change in behaviour: I no longer crash Firefox. Instead, when trying to navigate to the next sibling from the Page accessible, I now hear an error tone from NVDA. So, NVDA notices that there's something wrong, and Firefox does not crash. Without this patch, or with the current nightly, this error tone would not be heard, but Firefox would crash.
Attached patch patch2Splinter Review
since nsDocAccessible caches all children from its subtree then there is a direct child which mParent points to nsDocAccessible. Therefore I added cycle collection to it.
Attachment #330235 - Attachment is obsolete: true
Attachment #330244 - Flags: review?(marco.zehe)
Attachment #330235 - Flags: review?(marco.zehe)
(In reply to comment #2) > Does this fix our leak bugs, like bug 434491 can't reproduce on trunk , bug 420068 doesn't fix :(
(In reply to comment #16) > (In reply to comment #2) > > Does this fix our leak bugs, like bug 434491 > > can't reproduce on trunk there is leaks of nsAccessNode, patch doesn't help
Comment on attachment 330244 [details] [diff] [review] patch2 So far, no negative impact noticed. Behaviour with NVDA is the same as with previous patch, which means "error sound", but no crash. Also, the bogus document hasn't reappeared yet.
Comment on attachment 330244 [details] [diff] [review] patch2 r=me. I have been running with this patch for 2 days straight and didn't find any regressions. No crashes or other unexpected behavior occurred.
Attachment #330244 - Flags: review?(marco.zehe) → review+
Attachment #330244 - Flags: superreview?(neil)
Attachment #330244 - Flags: review?(Olli.Pettay)
Attachment #330244 - Flags: review?(aaronleventhal)
Comment on attachment 330244 [details] [diff] [review] patch2 >+NS_IMPL_CYCLE_COLLECTION_0(nsAccessNode) Can anyone actually create a raw access node? (Note: I don't actually see the point of NS_IMPL_CYCLE_COLLECTION_0 since an object that owns no collectable objects can't be part of a cycle.) >+NS_IMPL_CYCLE_COLLECTION_CLASS(nsAccessible) >+ >+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsAccessible, nsAccessNode) >+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParent) >+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFirstChild) >+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mNextSibling) >+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END >+ >+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsAccessible, nsAccessNode) >+ NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mParent) >+ NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFirstChild) >+ NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mNextSibling) >+NS_IMPL_CYCLE_COLLECTION_UNLINK_END Why not use NS_IMPL_CYCLE_COLLECTION_3?
(In reply to comment #20) > (From update of attachment 330244 [details] [diff] [review]) > >+NS_IMPL_CYCLE_COLLECTION_0(nsAccessNode) > Can anyone actually create a raw access node? > (Note: I don't actually see the point of NS_IMPL_CYCLE_COLLECTION_0 since an > object that owns no collectable objects can't be part of a cycle.) Yes, but I didn't found macros for this case. Object with cycle collections have specific addref/release method implementation, here I need that and plus redirect them to base class. > >+NS_IMPL_CYCLE_COLLECTION_CLASS(nsAccessible) > >+ > >+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsAccessible, nsAccessNode) > >+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParent) > >+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFirstChild) > >+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mNextSibling) > >+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END > >+ > >+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsAccessible, nsAccessNode) > >+ NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mParent) > >+ NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFirstChild) > >+ NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mNextSibling) > >+NS_IMPL_CYCLE_COLLECTION_UNLINK_END > Why not use NS_IMPL_CYCLE_COLLECTION_3? > because there is no NS_IMPL_CYCLE_COLLECTION_ INHERITED_3?
Sorry I wasn't being clear, but if the nsAccessNode class is never itself created as an object then it doesn't need to participate in cycle collection and nsAccessible doesn't need to implement inherited cycle collection.
(In reply to comment #22) > Sorry I wasn't being clear, but if the nsAccessNode class is never itself > created as an object then it doesn't need to participate in cycle collection > and nsAccessible doesn't need to implement inherited cycle collection. > There are cases when nsAccessNode is created (via COM's ISimple* interfaces when DOM node isn't accessible in the usual sense). Though I didn't catch you what the difference does it play?
(In reply to comment #23) > (In reply to comment #22) > > Sorry I wasn't being clear, but if the nsAccessNode class is never itself > > created as an object then it doesn't need to participate in cycle collection > > and nsAccessible doesn't need to implement inherited cycle collection. > > > > There are cases when nsAccessNode is created (via COM's ISimple* interfaces > when DOM node isn't accessible in the usual sense). Though I didn't catch you > what the difference does it play? > Do you mean in this case we wouldn't call AddRef/Release of nsAccessNode? And even we wouldn't implement those methods, right?
Comment on attachment 330244 [details] [diff] [review] patch2 >-class nsAccessNode: public nsIAccessNode, public nsPIAccessNode >+class nsAccessNode: public nsIAccessNode, >+ public nsPIAccessNode > { > public: // construction, destruction > nsAccessNode(nsIDOMNode *, nsIWeakReference* aShell); > virtual ~nsAccessNode(); > >- NS_DECL_ISUPPORTS >+ // NS_DECL_ISUPPORTS Remove, don't just comment out. > NS_IMETHODIMP nsAccessible::InvalidateChildren() > { > // Document has transformed, reset our invalid children and child count > > // Reset the sibling pointers, they will be set up again the next time > // CacheChildren() is called. > // Note: we don't want to start creating accessibles at this point, > // so don't use GetNextSibling() here. (bug 387252) >- nsAccessible* child = static_cast<nsAccessible*>(mFirstChild); >+ nsAccessible* child = static_cast<nsAccessible*>(mFirstChild.get()); >+// nsAccessible* child = static_cast<nsAccessible*>(mFirstChild); Same here.
Attachment #330244 - Flags: review?(Olli.Pettay) → review+
Blocks: 342045
(In reply to comment #21) > (In reply to comment #20) > > (From update of attachment 330244 [details] [diff] [review] [details]) > > >+NS_IMPL_CYCLE_COLLECTION_0(nsAccessNode) > > Can anyone actually create a raw access node? > > (Note: I don't actually see the point of NS_IMPL_CYCLE_COLLECTION_0 since an > > object that owns no collectable objects can't be part of a cycle.) peterv says that you need this so that subclasses can be cycle collected. > > Why not use NS_IMPL_CYCLE_COLLECTION_3? > because there is no NS_IMPL_CYCLE_COLLECTION_ INHERITED_3? Sorry, I hadn't realised that NS_IMPL_CYCLE_COLLECTION_3_AMBIGUOUS had been surreptitiously removed by bug 368549.
(In reply to comment #26) > (In reply to comment #21) > > because there is no NS_IMPL_CYCLE_COLLECTION_ INHERITED_3? > Sorry, I hadn't realised that NS_IMPL_CYCLE_COLLECTION_3_AMBIGUOUS had been > surreptitiously removed by bug 368549. *_AMBIGUOUS and *_INHERITED macros are very different. _AMBIGUOUS is for classes that that can't convert to/from nsISupports without an intermediate step (to clarify the ambiguity) in between, because the class inherits from nsISupports in multiple ways. The extra class given to a *_AMBIGUOUS macro is usually an interface. *_INHERITED macros are to forward to the base class implementation. The extra class given to a *_INHERITED macro is always a concrete class.
(In reply to comment #26) > (In reply to comment #21) > > (In reply to comment #20) > > > (From update of attachment 330244 [details] [diff] [review] [details] [details]) > > > >+NS_IMPL_CYCLE_COLLECTION_0(nsAccessNode) > > > Can anyone actually create a raw access node? > > > (Note: I don't actually see the point of NS_IMPL_CYCLE_COLLECTION_0 since an > > > object that owns no collectable objects can't be part of a cycle.) > peterv says that you need this so that subclasses can be cycle collected. So, I don't need to change anything?
Status: NEW → ASSIGNED
(In reply to comment #28) > So, I don't need to change anything? No. (In reply to comment #27) > (In reply to comment #26) > > (In reply to comment #21) > > > because there is no NS_IMPL_CYCLE_COLLECTION_ INHERITED_3? > > Sorry, I hadn't realised that NS_IMPL_CYCLE_COLLECTION_3_AMBIGUOUS had been > > surreptitiously removed by bug 368549. > *_AMBIGUOUS and *_INHERITED macros are very different. Ah yes, I should have realised when the macros used _base instead of Super.
Neil, any other comments?
Comment on attachment 330244 [details] [diff] [review] patch2 Sorry, I thought I'd done this one :-(
Attachment #330244 - Flags: superreview?(neil) → superreview+
Will we be warned when the cycle ends up getting used? Because it shouldn't have to be if we did things correctly.
Comment on attachment 330244 [details] [diff] [review] patch2 I'm basing my r= on Neil's sr= on the actual code. I have no issues with this going into the module.
Attachment #330244 - Flags: review?(aaronleventhal) → review+
Status: ASSIGNED → RESOLVED
Closed: 18 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla1.9.1a2
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: