Closed Bug 387203 Opened 17 years ago Closed 17 years ago

getFolderContents() can crash [@nsNavHistoryContainerResultNode::CloseContainer] when JS GC happens

Categories

(Firefox :: Bookmarks & History, defect)

defect
Not set
normal

Tracking

()

RESOLVED FIXED
Firefox 3 beta1

People

(Reporter: moco, Assigned: moco)

References

Details

Attachments

(6 files, 8 obsolete files)

10.15 KB, text/plain
Details
11.55 KB, text/plain
Details
8.16 KB, patch
asaf
: review+
Details | Diff | Splinter Review
1.97 KB, text/plain
Details
14.86 KB, patch
sicking
: review+
Details | Diff | Splinter Review
3.31 KB, text/plain
Details
getFolderContents() can crash when JS GC happens

with the patch in #378558 I am crashing when I attempt to copy the "root" bookmark in the left hand pane of the bookmark organizer.

What I think is going is that JS GC is happening, and we are garbage collecting "result" [see getFolderContents()]

  getFolderContents:
  function PU_getFolderContents(aFolderId, aExcludeItems, aExpandQueries) {
    var query = this.history.getNewQuery();
    query.setFolders([aFolderId], 1);
    var options = this.history.getNewQueryOptions();
    options.setGroupingMode([Ci.nsINavHistoryQueryOptions.GROUP_BY_FOLDER], 1);
    options.excludeItems = aExcludeItems;
    options.expandQueries = aExpandQueries;

    var result = this.history.executeQuery(query, options);
    result.root.containerOpen = true;
    return asContainer(result.root);
  },

See attachment #1 [details] [diff] [review] for the stack to when we GC.

Later, I'll crash in nsNavHistoryContainerResultNode::CloseContainer() because result points to freed memory.  See attachment #2 [details] [diff] [review] for the stack

Not, this is obviously not 100% reproducable, depending on when GC runs.
(I think cyen didn't see it with a new profile, but did with an old one.)

To fix this, in nsNavHistoryContainerResultNode, make mResult be a nsCOMPtr instead of a regular nsNavHistoryResult *.  This way, mResult won't get collected until the node is no longer referenced.

I'll attach a patch.
Attached patch patch to fix the crash (obsolete) — Splinter Review
Attachment #271318 - Flags: review?(dietrich)
this blocks cyen's bug, but crashes like this could be lurking in our code.  (I'll check breakpad / bugzilla.)
Blocks: 378558
Status: NEW → ASSIGNED
Flags: blocking-firefox3?
Summary: getFolderContents() can crash when JS GC happens → getFolderContents() can crash [@nsNavHistoryContainerResultNode::CloseContainer] when JS GC happens
Target Milestone: --- → Firefox 3 beta1
Comment on attachment 271318 [details] [diff] [review]
patch to fix the crash

I think now I'm leaking nsNavHistoryResult and nsNavHistorQueryNode objects, as they own each other strongly.

working on it...
Attachment #271318 - Attachment is obsolete: true
Attachment #271318 - Flags: review?(dietrich)
So we've a couple of issues here:
  1) Nodes cannot live without their containing result being strong-ref'ed somewhere else (in the caller).
  2) getFolderContents returns the root result node instead of the result itself.

To fix 1) you'd need to keep a strong reference to the result in the root node of it, implement cycle-collection, ...and cross your fingers.

We should fix 2) either way, I think.
working on both #1 and #2.

FWIW, Jonas agrees about #1.
Attached patch patch, v1 (obsolete) — Splinter Review
Comment on attachment 271686 [details] [diff] [review]
fix getFolderContents(), per mano

r=mano
Attachment #271686 - Flags: review?(mano) → review+
getFolderContents() cleanup landed:

Checking in places/content/controller.js;
/cvsroot/mozilla/browser/components/places/content/controller.js,v  <--  control
ler.js
new revision: 1.166; previous revision: 1.165
done
Checking in places/content/places.js;
/cvsroot/mozilla/browser/components/places/content/places.js,v  <--  places.js
new revision: 1.93; previous revision: 1.92
done
Checking in places/content/utils.js;
/cvsroot/mozilla/browser/components/places/content/utils.js,v  <--  utils.js
new revision: 1.48; previous revision: 1.47
done
Checking in preferences/selectBookmark.js;
/cvsroot/mozilla/browser/components/preferences/selectBookmark.js,v  <--  select
Bookmark.js
new revision: 1.7; previous revision: 1.6
done
Running with my patch, there are scenarious where we traverse the cycles, unlink, and release the objects during cycle collection.

But there are also some scenarios where we are leaking nsNavHistoryResult and nsNavHistoryContainerResultNode objects.

I'm not sure if we've always been leaking those objects or not, but I'll investigate.
Attached patch updated patch (obsolete) — Splinter Review
Attachment #271614 - Attachment is obsolete: true
Comment on attachment 272069 [details] [diff] [review]
updated patch

seeking review for the crash fix.

will spin off the leak issue into another bug.
Attachment #272069 - Flags: review?(mano)
Comment on attachment 272069 [details] [diff] [review]
updated patch

seeking additional review from Jonas.
Attachment #272069 - Flags: review?(jonas)
> will spin off the leak issue into another bug.

I have not checked in yet, due to the leak issue.

On simple startup / shutdown, there are new leaks are coming from the places toolbar and from exporting to bookmarks.html.  (I'm not opening the history or bookmark menu) 

before:

     |<----------------Class--------------->|<-----Bytes------>|<----------------Objects---------------->|<--------------References-------------->|
                                              Per-Inst   Leaked    Total      Rem      Mean       StdDev     Total      Rem      Mean       StdDev
   0 TOTAL                                          29      201   256931        6 ( 1201.82 +/-  1707.26)   830208        5 ( 1191.39 +/-  1900.05)
  62 StringAdopt                                     1        1     2559        1 (   76.31 +/-    25.32)        0        0 (    0.00 +/-     0.00)
 443 nsLocalFile                                    88      176     2492        2 (  270.45 +/-   152.13)    14008        2 (  317.19 +/-   184.98)
 567 nsStringBuffer                                  8       24    32624        3 ( 4693.88 +/-  2283.80)    59778        3 ( 5255.39 +/-  2489.45)

after:

     |<----------------Class--------------->|<-----Bytes------>|<----------------Objects---------------->|<--------------References-------------->|
                                              Per-Inst   Leaked    Total      Rem      Mean       StdDev     Total      Rem      Mean       StdDev
   0 TOTAL                                          29    93233   275197     2490 ( 1210.31 +/-  1682.38)   897915     2491 ( 1267.67 +/-  1965.81)
 465 nsNavHistoryContainerResultNode               144     5472       41       38 (   22.23 +/-    12.43)      400       38 (   32.13 +/-    12.46)
 466 nsNavHistoryFolderResultNode                  160     6080       39       38 (   20.45 +/-    11.61)      374       38 (   30.07 +/-    12.46)
 467 nsNavHistoryQuery                             112      224       11        2 (    5.40 +/-     2.33)       66        2 (    7.81 +/-     3.27)
 468 nsNavHistoryQueryOptions                       56      224       11        4 (    6.17 +/-     2.62)      163       40 (   23.40 +/-    14.89)
 470 nsNavHistoryResult                            144      288        5        2 (    3.00 +/-     1.31)      167       38 (   26.65 +/-    13.70)
 471 nsNavHistoryResultNode                        104    66976      647      644 (  325.48 +/-   187.75)     4066      644 (  461.51 +/-   209.92)
 569 nsStringBuffer                                  8    13512    33858     1689 ( 4763.13 +/-  2227.65)    63377     1689 ( 5234.77 +/-  2453.19)
 585 nsTArray_base                                   4      120     6412       30 (  706.45 +/-   234.27)        0        0 (    0.00 +/-     0.00)
 631 nsVoidArray                                     4      160     9927       40 ( 2107.78 +/-   981.31)        0        0 (    0.00 +/-     0.00)

I'm investigating.
> I'm investigating.

Sliding out of M7 to M8.  Not a UI blocker, and I won't have time during M7 to track down this leak.
Target Milestone: Firefox 3 M7 → Firefox 3 M8
Comment on attachment 272069 [details] [diff] [review]
updated patch

let's see if we can figure out the leak by M8, then make the trade.
Attachment #272069 - Flags: review?(mano)
Flags: blocking-firefox3? → blocking-firefox3+
Target Milestone: Firefox 3 M8 → Firefox 3 M9
the leak might be fixed by bug #397221. 

I'll try again, as we need this.
using XPCOM_MEM_LEAK_LOG, make-tree.pl, find-leakers.pl, and fix-macosx-stack.pl (thanks dbaron!) to figure out why.
Attachment #272069 - Attachment is obsolete: true
Comment on attachment 284996 [details] [diff] [review]
updated to trunk (for myk), still no progress on the leak

>Index: src/nsNavHistoryResult.cpp
>===================================================================

>+NS_IMPL_CYCLE_COLLECTION_0(nsNavHistoryResultNode)

If you think these objects are part of a cycle then they must be holding a strong reference to something. This says they hold on to nothing, so they can't be part of a cycle.
Unless it's only used as baseclass for objects that do hold on to things.
Do you need to traverse mRootNode in nsNavHistoryResultNode?
> Do you need to traverse mRootNode in nsNavHistoryResultNode?

that's not a member of nsNavHistoryResultNode, but of nsNavHistoryResult, and I'm already traversing it.
I think I have it!  

I need to traverse and unlink mChildren (in addition to mResult), in the cycle collector macros for nsNavHistoryContainerResultNode.

triple checking now.
Heh, I'll just mid-aired trying to post this:

Shouldn't you traverse mChildren in nsNavHistoryContainerResultNode? Note that
the cycle collector won't collect a cycle unless it's aware of all the edges
that hold nodes in that cycle.
Attached patch patch for review (obsolete) — Splinter Review
Attachment #285150 - Attachment is obsolete: true
Attachment #285152 - Flags: review?
Attachment #285152 - Flags: approval1.9?
Attachment #285152 - Flags: review? → review?(jonas)
Attached patch patch for review (obsolete) — Splinter Review
Attachment #285152 - Attachment is obsolete: true
Attachment #285154 - Flags: review?(jonas)
Attachment #285152 - Flags: review?(jonas)
Attachment #285152 - Flags: approval1.9?
Comment on attachment 285154 [details] [diff] [review]
patch for review

>-NS_INTERFACE_MAP_BEGIN(nsNavHistoryResult)
>+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsNavHistoryResult)
>   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsINavHistoryResult)
>   NS_INTERFACE_MAP_STATIC_AMBIGUOUS(nsNavHistoryResult)
>   NS_INTERFACE_MAP_ENTRY(nsINavHistoryResult)
>   NS_INTERFACE_MAP_ENTRY(nsINavBookmarkObserver)
>   NS_INTERFACE_MAP_ENTRY(nsINavHistoryObserver)
>   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
>+  NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsNavHistoryResult)
> NS_INTERFACE_MAP_END

180 #define NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(_class) \
181   NS_INTERFACE_MAP_BEGIN(_class)                        \
182     NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(_class)   \

...suggests the second change here is unnecessary.
thanks waldo.
Attachment #285154 - Attachment is obsolete: true
Attachment #285158 - Flags: review?(jonas)
Attachment #285154 - Flags: review?(jonas)
fixed

Checking in nsNavBookmarks.cpp;
/cvsroot/mozilla/toolkit/components/places/src/nsNavBookmarks.cpp,v  <--  nsNavB
ookmarks.cpp
new revision: 1.123; previous revision: 1.122
done
Checking in nsNavHistory.cpp;
/cvsroot/mozilla/toolkit/components/places/src/nsNavHistory.cpp,v  <--  nsNavHis
tory.cpp
new revision: 1.178; previous revision: 1.177
done
Checking in nsNavHistoryResult.cpp;
/cvsroot/mozilla/toolkit/components/places/src/nsNavHistoryResult.cpp,v  <--  ns
NavHistoryResult.cpp
new revision: 1.119; previous revision: 1.118
done
Checking in nsNavHistoryResult.h;
/cvsroot/mozilla/toolkit/components/places/src/nsNavHistoryResult.h,v  <--  nsNa
vHistoryResult.h
new revision: 1.48; previous revision: 1.47
done
Status: ASSIGNED → RESOLVED
Closed: 17 years ago
Resolution: --- → FIXED
Bug 451915 - move Firefox/Places bugs to Firefox/Bookmarks and History. Remove all bugspam from this move by filtering for the string "places-to-b-and-h".

In Thunderbird 3.0b, you do that as follows:
Tools | Message Filters
Make sure the correct account is selected. Click "New"
Conditions: Body   contains   places-to-b-and-h
Change the action to "Delete Message".
Select "Manually Run" from the dropdown at the top.
Click OK.

Select the filter in the list, make sure "Inbox" is selected at the bottom, and click "Run Now". This should delete all the bugspam. You can then delete the filter.

Gerv
Component: Places → Bookmarks & History
QA Contact: places → bookmarks
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: