Closed
Bug 820182
Opened 13 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•13 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•13 years ago
|
||
Attachment #690894 -
Flags: review?(ehsan)
Comment 3•13 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•13 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•13 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•13 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•13 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•13 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•13 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•13 years ago
|
||
OK, we're in violent agreement it seems!
| Assignee | ||
Comment 11•13 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•13 years ago
|
||
Attachment #690894 -
Attachment is obsolete: true
Attachment #691086 -
Flags: review?(ehsan)
Comment 13•13 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•13 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•13 years ago
|
||
And Neil spotted two things that I missed! Please fix those too. Thanks!
| Assignee | ||
Comment 16•13 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•13 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•13 years ago
|
||
| Assignee | ||
Updated•13 years ago
|
Whiteboard: [leave open]
Comment 19•13 years ago
|
||
| Assignee | ||
Comment 20•13 years ago
|
||
Comment 21•13 years ago
|
||
| 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
•