Closed
Bug 820182
Opened 12 years ago
Closed 12 years ago
nsISupportsArray::ElementAt() is particularly evil
Categories
(Core :: XPCOM, defect)
Core
XPCOM
Tracking
()
RESOLVED
FIXED
mozilla20
People
(Reporter: tbsaunde, Assigned: tbsaunde)
References
Details
Attachments
(1 file, 1 obsolete file)
8.62 KB,
patch
|
ehsan.akhgari
:
review+
|
Details | Diff | Splinter Review |
it returns an addrefed raw nsISupports* QED. We can either just make it return a already_AddRefed, or remove it all together. the later may be safer if dont_AddRef() doesn't gaurd against being passed a already_AddRefed, since some of the callers expect the crazy behavior and use dont_AddRef().
Assignee | ||
Comment 1•12 years ago
|
||
So, I started looking into what had to be changed for ElementAt() to go away, and found some lovely code in rdf/base/src/nsInMemoryDatasource.cpp which I think maybe uses if there is an array to decide what to do lter on, but I don't trust my understanding of it enough to change it much less think people will be interested in reviewing it, so I think getting rid of ElementAt() is probably out for now. However it looks like dont_AddRef() does handle being passed an already_AddReed so that seems to be a reasonable option.
Assignee | ||
Comment 2•12 years ago
|
||
Attachment #690894 -
Flags: review?(ehsan)
Comment 3•12 years ago
|
||
Comment on attachment 690894 [details] [diff] [review] bug 820182 - nsISupportsArray::ElementAt() should return already_AddRefed<nsISupports> Review of attachment 690894 [details] [diff] [review]: ----------------------------------------------------------------- r=me, assuming that you've verified that this covers every caller of ElementAt. I'm a bit surprised that there are no callers that use dont_AddRef, for example. I have not looked through all of the call sites, but I'm assuming that you have.
Attachment #690894 -
Flags: review?(ehsan) → review+
Comment 4•12 years ago
|
||
For what it's worth, the last time I tried making this change (many years ago, granted) the issue described in comment 3 is precisely what I ran into: lots of code that assumed the current model, not limited to using dont_AddRef even... In particular, there's a ton of mailnews code that uses nsISupportsArray; I'm not sure whether you built comm-central or looked into the callsites there.
Comment 5•12 years ago
|
||
Then again, I somewhat recall renaming ElementAt() in my tree, going through all the compile failures and fixing all the random leaks that I found, so maybe it's ok now... It's just hard to tell. :(
Comment 6•12 years ago
|
||
Yeah, Trevor, at the very least you need to build Firefox, Thunderbird and SeaMonkey to make sure none of them break. Renaming ElementAt temporarily is probably a good idea if you want the compiler to help you catch all of the call sites.
Assignee | ||
Comment 7•12 years ago
|
||
So, actually it turns out that its silly to write something like dont_AddRef(myArray->ElementAt(i)) now, but not actually harmful, because we define dont_AddRef() as template <class T> inline const already_AddRefed<T> dont_AddRef( T* aRawPtr ) { return already_AddRefed<T>(aRawPtr); } template <class T> inline const already_AddRefed<T> dont_AddRef( const already_AddRefed<T> aAlreadyAddRefedPtr ) { return aAlreadyAddRefedPtr; } why we have that second overload I have no idea, it seems like it would be a good idea to remove it, but it means that its somewhat easier to get things to compile and be correct when making a change like this.
Comment 8•12 years ago
|
||
(In reply to comment #7) > So, actually it turns out that its silly to write something like > dont_AddRef(myArray->ElementAt(i)) now, but not actually harmful, because we > define dont_AddRef() as No, it's not silly at all, that's what it's designed to do. For example, the following code: nsCOMPtr<nsIFoo> foo = mArray->ElementAt(i); will address the i'th element two times, once inside ElementAt and once inside nsCOMPtr's constructor. So effectively you'll leak a reference. If you rewrite this as: nsCOMPtr<nsIFoo> foo = dont_AddRef(mArray->ElementAt(i)); then the second AddRef will be avoided since nsCOMPtr's ctor knows to not call AddRef if it receives an already_AddRefed object. > template <class T> > inline > const already_AddRefed<T> > dont_AddRef( T* aRawPtr ) > { > return already_AddRefed<T>(aRawPtr); > } > > template <class T> > inline > const already_AddRefed<T> > dont_AddRef( const already_AddRefed<T> aAlreadyAddRefedPtr ) > { > return aAlreadyAddRefedPtr; > } > > why we have that second overload I have no idea, it seems like it would be a > good idea to remove it, but it means that its somewhat easier to get things to > compile and be correct when making a change like this. Hmm, actually with this second overload, it _should_ be ok if callers use dont_AddRef with your patch, since then they would effectively be using the second overload. But still that's not very hygenic...
Assignee | ||
Comment 9•12 years ago
|
||
(In reply to Ehsan Akhgari [:ehsan] from comment #8) > (In reply to comment #7) > > So, actually it turns out that its silly to write something like > > dont_AddRef(myArray->ElementAt(i)) now, but not actually harmful, because we > > define dont_AddRef() as > > No, it's not silly at all, that's what it's designed to do. > > For example, the following code: I should have been more clear, by "now" I meant a world in which ElementAt() returns already_AddRefed, because that is the state of the world in my tree. > > template <class T> > > inline > > const already_AddRefed<T> > > dont_AddRef( const already_AddRefed<T> aAlreadyAddRefedPtr ) > > { > > return aAlreadyAddRefedPtr; > > } > > > > why we have that second overload I have no idea, it seems like it would be a > > good idea to remove it, but it means that its somewhat easier to get things to > > compile and be correct when making a change like this. > > Hmm, actually with this second overload, it _should_ be ok if callers use > dont_AddRef with your patch, since then they would effectively be using the > second overload. But still that's not very hygenic... yes, that's what I meant by it being silly.
Comment 10•12 years ago
|
||
OK, we're in violent agreement it seems!
Assignee | ||
Comment 11•12 years ago
|
||
standard8, neil I'm about to attach a patch removing the last few uses of this method in m-c and the method itself. Any idea how much work there is on the c-c side? or would you like to tell me how to build c-c to write you guys a patch?
Assignee | ||
Comment 12•12 years ago
|
||
Attachment #690894 -
Attachment is obsolete: true
Attachment #691086 -
Flags: review?(ehsan)
Comment 13•12 years ago
|
||
Comment on attachment 691086 [details] [diff] [review] bug 820182 - remove nsISupportsArray::ElementAt() IIRC the last big mailnews use of ElementAt went away as part of bug 379806 a mere 4 years ago. I didn't notice any current consumers. >- mCurrent = static_cast<nsIRDFResource *> >- (mHashArcs->ElementAt(itemCount)); >+ mHashArcs->GetElementAt(itemCount, >+ reinterpret_cast<nsISupports**>(&mCurrent)); Shouldn't this change to do_QueryElementAt too? >+native alreadyAddRefedNSISupports(already_AddRefed<nsISupports>); Obsolete? >+NS_IMETHODIMP >+nsSupportsArray::GetElementAt(uint32_t aIndex, nsISupports **aOutPtr) > { > if (aIndex < mCount) { >- nsISupports* element = mArray[aIndex]; >- NS_IF_ADDREF(element); >- return element; >+ NS_IF_ADDREF(*aOutPtr = mArray[aIndex]); > } >- return 0; >+ return NS_OK; Need to set your result before returning.
Comment 14•12 years ago
|
||
Comment on attachment 691086 [details] [diff] [review] bug 820182 - remove nsISupportsArray::ElementAt() Review of attachment 691086 [details] [diff] [review]: ----------------------------------------------------------------- ::: xpcom/ds/nsISupportsArray.idl @@ +31,5 @@ > #define NS_SUPPORTSARRAY_CLASSNAME "Supports Array" > > %} > > +native alreadyAddRefedNSISupports(already_AddRefed<nsISupports>); This is no longer needed.
Attachment #691086 -
Flags: review?(ehsan) → review+
Comment 15•12 years ago
|
||
And Neil spotted two things that I missed! Please fix those too. Thanks!
Assignee | ||
Comment 16•12 years ago
|
||
(In reply to neil@parkwaycc.co.uk from comment #13) > Comment on attachment 691086 [details] [diff] [review] > bug 820182 - remove nsISupportsArray::ElementAt() > > IIRC the last big mailnews use of ElementAt went away as part of bug 379806 > a mere 4 years ago. I didn't notice any current consumers. great > >- mCurrent = static_cast<nsIRDFResource *> > >- (mHashArcs->ElementAt(itemCount)); > >+ mHashArcs->GetElementAt(itemCount, > >+ reinterpret_cast<nsISupports**>(&mCurrent)); > Shouldn't this change to do_QueryElementAt too? I don't see a reason why not > >+native alreadyAddRefedNSISupports(already_AddRefed<nsISupports>); > Obsolete? yes
Assignee | ||
Comment 17•12 years ago
|
||
Turns out this depends on other ElementAt() removals in bug 819936 so it won't be landing for a little while.
Assignee | ||
Comment 18•12 years ago
|
||
remote: https://hg.mozilla.org/integration/mozilla-inbound/rev/163f1b12bdef
Assignee | ||
Updated•12 years ago
|
Whiteboard: [leave open]
Assignee | ||
Comment 20•12 years ago
|
||
https://hg.mozilla.org/integration/mozilla-inbound/rev/06ae0a5f4d9c
Assignee | ||
Updated•12 years ago
|
Status: NEW → RESOLVED
Closed: 12 years ago
Resolution: --- → FIXED
Whiteboard: [leave open]
Target Milestone: --- → mozilla20
You need to log in
before you can comment on or make changes to this bug.
Description
•