Closed
Bug 73289
Opened 24 years ago
Closed 24 years ago
plugins must be released even if plugin host is leaked
Categories
(Core Graveyard :: Plug-ins, defect)
Tracking
(Not tracked)
VERIFIED
FIXED
People
(Reporter: sean, Assigned: serhunt)
Details
(Keywords: memory-leak)
Attachments
(7 files)
(deleted),
text/html
|
Details | |
(deleted),
patch
|
Details | Diff | Splinter Review | |
(deleted),
patch
|
Details | Diff | Splinter Review | |
(deleted),
patch
|
Details | Diff | Splinter Review | |
(deleted),
patch
|
Details | Diff | Splinter Review | |
(deleted),
patch
|
Details | Diff | Splinter Review | |
(deleted),
patch
|
Details | Diff | Splinter Review |
If javascript in a page causes an exception to be thrown and the plugin host was
referenced, the plugin host gets leaked and fails to shutdown and release the
nsIPlugins that it has addref'd but not yet released.
Will attach testcase.
This causes the Beatnik Player plugin to crash at shutdown.
Reporter | ||
Comment 1•24 years ago
|
||
Reporter | ||
Comment 2•24 years ago
|
||
There's a line in the nsPluginHostImpl ctor:
obsService->AddObserver(this, NS_LITERAL_STRING("quit-application").get());
seems like that should address the leak, but I'm not seeing
nsPluginHostImpl::Observe getting called. Did the "quit-application" topic
string change recently?
Reporter | ||
Comment 3•24 years ago
|
||
FYI: just filed bug 73495. I'm getting a leak of the plugin host whenever I do
document.plugins.length in javascript now (pretty sure I wasn't last week, so I
think it's a new, separate bug).
Reporter | ||
Comment 4•24 years ago
|
||
The main problem here is that now that host is holding references to a plugin
module's nsIPlugin (because of bug 45009), any time the host is not properly
shutdown we have the potential for a crash in third party plugins. The patch
for 45009 made the host an observer of the "quit-application" topic. I have
not seen the topic ever fired. Will attach patch that makes the host an
observer of the "xpcom-shutdown" topic.
Reporter | ||
Comment 5•24 years ago
|
||
Reporter | ||
Comment 6•24 years ago
|
||
The patch also ensures better cleanup of resources even if the host itself is
never destroyed. Moved cleanup code from the host dtor into it's Destroy
method which is already protected against multiple calls.
Keywords: review
Reporter | ||
Comment 7•24 years ago
|
||
The attached patch might also address bug 65661.
Andrei, can you please review?
Moving clean up code to Destroy method is right thing to do. Is observer
reliably called on xpcom shutdown?
I assume you have tested it and looks like it does address the issue.
ar=av
Reporter | ||
Comment 9•24 years ago
|
||
xpcom-shutdown is called very reliably and I've tested the patch with Acrobat,
Flash and Beatnik.
cc'ing Chris. Can you please sr?
Reporter | ||
Comment 10•24 years ago
|
||
I should note that the patch doesn't actually address the leak of the plugin
host, but it addresses the bad things that happen to plugins that occur when
the host is leaked.
Reporter | ||
Comment 11•24 years ago
|
||
adding mozilla0.9, beatnik keywords
severity -> critical
Severity: normal → critical
Keywords: beatnik,
mozilla0.9
Comment 12•24 years ago
|
||
The patch looks fine - sr=attinasi
One question though (not something you changed, but I'm curious): why is
mPlugins set to mPlugins->next, previously in the destructor and now in the
callback? Also, do you need to remove the observer that you added to the
observer service? It doesn't look like it was being removed before but I thought
I'd ask.
Assignee | ||
Comment 13•24 years ago
|
||
>One question though (not something you changed, but I'm curious): why is
>mPlugins set to mPlugins->next, previously in the destructor and now in the
>callback?
This is a linked list demolition going from the head to the tail. You are
talking about while cycle, right?
Comment 14•24 years ago
|
||
yup - I see now, my mistake - sorry.
Reporter | ||
Comment 15•24 years ago
|
||
Reporter | ||
Comment 16•24 years ago
|
||
>Also, do you need to remove the observer that you added to the
>observer service? It doesn't look like it was being removed before
Marc, you're question prompted me to revisit the Observe callback. I tried
removing the observer but it appears that doing so screws up the notifications
for other observers of the same topic. I've attached an updated patch with my
attempt at removing the observer (but commented out with a reason). I also
conditionalized the Destroy action so that any topics that might get added in
the future don't cause problems.
Could you take another gander at this patch?
Reporter | ||
Comment 17•24 years ago
|
||
ugh: you're -> your
Reporter | ||
Comment 18•24 years ago
|
||
Reporter | ||
Comment 19•24 years ago
|
||
OK - final patch hopefully. Moved the RemoveObserver calls to the host dtor.
Comment 20•24 years ago
|
||
Ah, nice. So I wonder if not removing the observer was causing some kind of leak
before. (my previous sr still applies - thanks for checking sean).
Reporter | ||
Comment 21•24 years ago
|
||
I think nsObserverList holds a weak reference to observers. If it were a
strong ref, then the host dtor wouldn't get called since there'd be a circular
dependency - unless the observerList automatically releases the observers it
contains, in which case failure to call RemoveObserver wouldn't be cause for a
leak anyway.
Thanks for the comments and sr.
Reporter | ||
Comment 22•24 years ago
|
||
changing summary to reflect what was actually fixed (old summary: plugin host
leaked if js exception thrown)
status -> fixed
Checking in nsPluginHostImpl.cpp;
/cvsroot/mozilla/modules/plugin/nglsrc/nsPluginHostImpl.cpp,v <-- nsPluginHost
Impl.cpp
new revision: 1.218; previous revision: 1.217
done
Status: NEW → RESOLVED
Closed: 24 years ago
Keywords: review
Resolution: --- → FIXED
Summary: plugin host leaked if js exception thrown → plugins must be released even if plugin host is leaked
Reporter | ||
Updated•24 years ago
|
Status: RESOLVED → REOPENED
Resolution: FIXED → ---
Reporter | ||
Comment 23•24 years ago
|
||
crap - my patch broke the Sun build. Commented out the offending lines:
http://bonsai.mozilla.org/cvsquery.cgi?
module=MozillaTinderboxAll&branch=HEAD&cvsroot=/cvsroot&date=explicit&mindate=98
6007600&maxdate=986008320&who=sean%25beatnik.com
Should this:
if (NS_LITERAL_STRING(NS_XPCOM_SHUTDOWN_OBSERVER_ID) == aTopic ||
NS_LITERAL_STRING("quit-application") == aTopic)
be this:
if (NS_LITERAL_STRING(NS_XPCOM_SHUTDOWN_OBSERVER_ID).get() == aTopic ||
NS_LITERAL_STRING("quit-application").get() == aTopic)
I don't have a Sun machine at my disposal to test this. Any advice?
Comment 24•24 years ago
|
||
No, use .Equals instead of ==, so:
if (NS_LITERAL_STRING(NS_XPCOM_SHUTDOWN_OBSERVER_ID).Equals(aTopic) ||
NS_LITERAL_STRING("quit-application").Equals(aTopic))
Comment 25•24 years ago
|
||
jag, what sean did should work IMO. scc, please comment.
Reporter | ||
Comment 26•24 years ago
|
||
I sent mail to Scott Friday night and got the following response:
>>>
You do know you are comparing two pointers now? It seems unlikely
those two pointers would ever be the same pointer. You probably want
to say something like
NS_LITERAL_STRING("foo").Equals(aTopic) // or
NS_LITERAL_STRING("foo") == nsLiteralString(aTopic)
...so that you compare the _contents_ of two strings. Right now,
you're just testing to see if two pointers both point to the same
location in memory. A lot of people make this mistake. I would like
to make it obvious to people that comparing two pointers does not
compare strings. Can you tell me what gave you that impression so
that I can figure out how to better educate people not to do this? By
the way, it's not that I don't _want_ to make this compare two
strings; it's that in C++, you can't override operations for built-in
types. And pointers are built-in types. So I can't make
|operator==(const PRUnichar*, const PRUnichar*)| do anything different
than it already does, which is the same thing it does for any other
pointer.
<<<
aTopic is const PRUnichar *. I thought I was using operator == defined in
template class basic_nsAReadableString but didn't notice that it is only defined
to compare to another basic_nsAReadableString. It's not that I thought I was
comparing 2 pointers but that I was invoking the class nsLiteralString operator
== which does a string compare.
Reporter | ||
Comment 27•24 years ago
|
||
So after wondering what was really happening with my original patch all weekend
I find that it does do a string compare and not a pointer compare on win32 - it
does the right thing. Although it's not actually invoking nsLiteralString
operator ==. It works thanks to this macro in nsAReadableString.h:
NS_DEF_TEMPLATE_STRING_COMPARISON_OPERATORS(basic_nsAReadableString<CharT>,
CharT)
which eventually routes operator == calls to:
template <class CharT>
int Compare( const basic_nsAReadableString<CharT>& lhs, const
basic_nsAReadableString<CharT>& rhs )
Here's the Sun error log:
nsPluginHostImpl.cpp: In method `unsigned int nsPluginHostImpl::Observe(class
nsISupports *, const short unsigned int *, const short unsigned int *)':
nsPluginHostImpl.cpp:4330: no match for `operator ==(class
NS_ConvertASCIItoUCS2, const short unsigned int *)'
nsPluginHostImpl.cpp:4331: no match for `operator ==(class
NS_ConvertASCIItoUCS2, const short unsigned int *)'
It looks like the reason the patch broke on Sun is that:
1. HAVE_CPP_2BYTE_WCHAR_T is not defined
2. there are no NS_DEF_TEMPLATE_STRING_COMPARISON_OPERATORS macros for
NS_ConvertASCIItoUCS2.
Scott, does this make sense?
Reporter | ||
Comment 28•24 years ago
|
||
Moot point. The macro NS_DEF_TEMPLATE_STRING_COMPARISON_OPERATORS no longer
exists and the original patch no longer compiles on Win32 or Mac.
Attaching patch correction.
Does the previous sr apply to this correction?
Reporter | ||
Comment 29•24 years ago
|
||
Assignee | ||
Comment 30•24 years ago
|
||
Sean, has it got in?
Reporter | ||
Comment 31•24 years ago
|
||
No - I think I need an r and sr on the last patch that fixes the string
comparison problem:
http://bugzilla.mozilla.org/showattachment.cgi?attach_id=29626.
Comment 32•24 years ago
|
||
sr=attinas for last patch (id=29626)
Comment 33•24 years ago
|
||
According to scc, something like:
NS_LITERAL_STRING(SOME_DEFINED_STRING)
is not guaranteed to compile because it depends on the order the preprocessor
processes the macros: on platforms where NS_LITERAL_STRING resolves to
nsLocalString(L..., ...) you could end up with
nsLocalString(LSOME_DEFINED_STRING, ...) -> unknown LSOME_DEFINED_STRING,
instead of NS_LITERAL_STRING("some string") -> nsLocalString(L"some string",
...).
I suggest you use NS_LITERAL_STRING("xpcom-shutdown") instead.
Reporter | ||
Comment 34•24 years ago
|
||
Reporter | ||
Comment 35•24 years ago
|
||
updated patch per Jag's comment but rather than NS_LITERAL_STRING("xpcom-
shutdown") I assigned NS_XPCOM_SHUTDOWN_OBSERVER_ID to an nsAutoString.
Reporter | ||
Comment 36•24 years ago
|
||
Jag: can you please review?
http://bugzilla.mozilla.org/showattachment.cgi?attach_id=31349
Comment 37•24 years ago
|
||
I knew I should've left in the "or if you want to keep
NS_XPCOM_SHUTDOWN_OBSERVER_ID, use
NS_ConvertASCIItoUCS2(NS_XPCOM_SHUTDOWN_OBSERVER_ID)."
This can be used as a drop-in replacement (it's what NS_LITERAL_STRING defines
to on platforms which don't support compile time conversion to 16-bit string
literals).
So:
- obsService->AddObserver(this,
NS_LITERAL_STRING(NS_XPCOM_SHUTDOWN_OBSERVER_ID).get());
+ obsService->AddObserver(this,
NS_ConvertASCIItoUCS2(NS_XPCOM_SHUTDOWN_OBSERVER_ID).get());
- obsService->RemoveObserver(this,
NS_LITERAL_STRING(NS_XPCOM_SHUTDOWN_OBSERVER_ID).get());
+ obsService->RemoveObserver(this,
NS_ConvertASCIItoUCS2(NS_XPCOM_SHUTDOWN_OBSERVER_ID).get());
-// if (NS_LITERAL_STRING(NS_XPCOM_SHUTDOWN_OBSERVER_ID) == aTopic ||
-// NS_LITERAL_STRING("quit-application") == aTopic)
+ if (NS_ConvertASCIItoUCS2(NS_XPCOM_SHUTDOWN_OBSERVER_ID).Equals(aTopic) ||
+ NS_LITERAL_STRING("quit-application").Equals(aTopic))
Reporter | ||
Comment 38•24 years ago
|
||
Reporter | ||
Comment 39•24 years ago
|
||
One macro or another... I think it might be better to keep the
NS_XPCOM_SHUTDOWN_OBSERVER_ID macro in case the string ever changes (if we used
a string literal, it would compile but stop working). Jag, one more time?
Comment 40•24 years ago
|
||
r=jag
Comment 41•24 years ago
|
||
Still looks OK to me - thanks sean - sr=attinasi
Reporter | ||
Comment 42•24 years ago
|
||
string changes finally checked in:
Checking in nsPluginHostImpl.cpp;
/cvsroot/mozilla/modules/plugin/nglsrc/nsPluginHostImpl.cpp,v <--
nsPluginHostImpl.cpp
new revision: 1.234; previous revision: 1.233
done
Thanks everyone!
Status: REOPENED → RESOLVED
Closed: 24 years ago → 24 years ago
Resolution: --- → FIXED
Updated•2 years ago
|
Product: Core → Core Graveyard
You need to log in
before you can comment on or make changes to this bug.
Description
•