зеркало из https://github.com/mozilla/pjs.git
Make the nsPluginInstanceTag destructor non-recursive to avoid exhausting stack space. b=486349 r+sr=jst
This commit is contained in:
Родитель
de45d635f7
Коммит
3db17e0fb0
|
@ -160,6 +160,17 @@
|
|||
#include <gdk/gdkx.h> // for GDK_DISPLAY()
|
||||
#endif
|
||||
|
||||
// Null out a strong ref to a linked list iteratively to avoid
|
||||
// exhausting the stack (bug 486349).
|
||||
#define NS_ITERATIVE_UNREF_LIST(type_, list_, mNext_) \
|
||||
{ \
|
||||
while (list_) { \
|
||||
type_ temp = list_->mNext_; \
|
||||
list_->mNext_ = nsnull; \
|
||||
list_ = temp; \
|
||||
} \
|
||||
}
|
||||
|
||||
// this is the name of the directory which will be created
|
||||
// to cache temporary files.
|
||||
#define kPluginTmpDirName NS_LITERAL_CSTRING("plugtmp")
|
||||
|
@ -407,7 +418,6 @@ PRBool nsPluginInstanceTagList::remove(nsPluginInstanceTag * plugin)
|
|||
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
|
||||
if (p == plugin) {
|
||||
PRBool lastInstance = IsLastInstance(p);
|
||||
nsPluginTag *pluginTag = p->mPluginTag;
|
||||
|
||||
if (p == mFirst)
|
||||
mFirst = p->mNext;
|
||||
|
@ -417,18 +427,26 @@ PRBool nsPluginInstanceTagList::remove(nsPluginInstanceTag * plugin)
|
|||
if (prev && !prev->mNext)
|
||||
mLast = prev;
|
||||
|
||||
delete p;
|
||||
if (lastInstance) {
|
||||
nsRefPtr<nsPluginTag> pluginTag = p->mPluginTag;
|
||||
|
||||
if (lastInstance && pluginTag) {
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPrefBranch> pref(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
delete p;
|
||||
|
||||
PRBool unloadPluginsASAP = PR_FALSE;
|
||||
rv = pref->GetBoolPref("plugins.unloadASAP", &unloadPluginsASAP);
|
||||
if (NS_SUCCEEDED(rv) && unloadPluginsASAP)
|
||||
pluginTag->TryUnloadPlugin();
|
||||
if (pluginTag) {
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPrefBranch> pref(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool unloadPluginsASAP = PR_FALSE;
|
||||
rv = pref->GetBoolPref("plugins.unloadASAP", &unloadPluginsASAP);
|
||||
if (NS_SUCCEEDED(rv) && unloadPluginsASAP)
|
||||
pluginTag->TryUnloadPlugin();
|
||||
}
|
||||
else
|
||||
NS_ASSERTION(pluginTag, "pluginTag was not set, plugin not shutdown");
|
||||
}
|
||||
else
|
||||
delete p;
|
||||
|
||||
mCount--;
|
||||
return PR_TRUE;
|
||||
|
@ -786,6 +804,8 @@ nsPluginTag::nsPluginTag(const char* aName,
|
|||
|
||||
nsPluginTag::~nsPluginTag()
|
||||
{
|
||||
NS_ASSERTION(!mNext, "Risk of exhausting the stack space, bug 486349");
|
||||
|
||||
TryUnloadPlugin();
|
||||
|
||||
// Remove mime types added to the category manager
|
||||
|
@ -2436,14 +2456,10 @@ nsPluginStreamListenerPeer::VisitHeader(const nsACString &header, const nsACStri
|
|||
}
|
||||
|
||||
nsPluginHost::nsPluginHost()
|
||||
// No need to initialize members to nsnull, PR_FALSE etc because this class
|
||||
// has a zeroing operator new.
|
||||
: mJavaEnabled(PR_TRUE)
|
||||
{
|
||||
mPluginsLoaded = PR_FALSE;
|
||||
mDontShowBadPluginMessage = PR_FALSE;
|
||||
mIsDestroyed = PR_FALSE;
|
||||
mOverrideInternalTypes = PR_FALSE;
|
||||
mAllowAlienStarHandler = PR_FALSE;
|
||||
mDefaultPluginDisabled = PR_FALSE;
|
||||
mJavaEnabled = PR_TRUE;
|
||||
|
||||
gActivePluginList = &mPluginInstanceTagList;
|
||||
|
||||
|
@ -2496,7 +2512,6 @@ nsPluginHost::nsPluginHost()
|
|||
PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("nsPluginHost::ctor\n"));
|
||||
PR_LogFlush();
|
||||
#endif
|
||||
mCachedPlugins = nsnull;
|
||||
}
|
||||
|
||||
nsPluginHost::~nsPluginHost()
|
||||
|
@ -2957,19 +2972,8 @@ NS_IMETHODIMP nsPluginHost::Destroy()
|
|||
mPluginPath = nsnull;
|
||||
}
|
||||
|
||||
while (mPlugins) {
|
||||
nsRefPtr<nsPluginTag> temp = mPlugins->mNext;
|
||||
// while walking through the list of the plugins see if we still have anything
|
||||
// to shutdown some plugins may have never created an instance but still expect
|
||||
// the shutdown call see bugzilla bug 73071
|
||||
// with current logic, no need to do anything special as nsIPlugin::Shutdown
|
||||
// will be performed in the destructor
|
||||
mPlugins->mNext = nsnull;
|
||||
mPlugins = temp;
|
||||
}
|
||||
|
||||
// Delete any remaining cached plugins list
|
||||
mCachedPlugins = nsnull;
|
||||
NS_ITERATIVE_UNREF_LIST(nsRefPtr<nsPluginTag>, mPlugins, mNext);
|
||||
NS_ITERATIVE_UNREF_LIST(nsRefPtr<nsPluginTag>, mCachedPlugins, mNext);
|
||||
|
||||
// Lets remove any of the temporary files that we created.
|
||||
if (sPluginTempDir) {
|
||||
|
@ -3511,6 +3515,7 @@ NS_IMETHODIMP nsPluginHost::SetUpPluginInstance(const char *aMimeType,
|
|||
return rv;
|
||||
|
||||
// other failure return codes may be not fatal, so we can still try
|
||||
aOwner->SetInstance(nsnull); // avoid assert about setting it twice
|
||||
rv = TrySetUpPluginInstance(aMimeType, aURL, aOwner);
|
||||
}
|
||||
|
||||
|
@ -4449,7 +4454,6 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile * pluginsDir,
|
|||
// we cannot get here if the plugin has just been added
|
||||
// and thus |pluginTag| is not from cache, because otherwise
|
||||
// it would not be present in the list;
|
||||
// so there is no need to delete |pluginTag| -- it _is_ from the cache info list.
|
||||
bAddIt = PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
@ -4463,12 +4467,6 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile * pluginsDir,
|
|||
if (pluginTag->IsEnabled())
|
||||
pluginTag->RegisterWithCategoryManager(mOverrideInternalTypes);
|
||||
}
|
||||
else if (!pluginTag->HasFlag(NS_PLUGIN_FLAG_UNWANTED)) {
|
||||
// we don't need it, delete it;
|
||||
// but don't delete unwanted plugins since they are cached
|
||||
// in the cache info list and will be deleted later
|
||||
pluginTag = nsnull;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -4582,7 +4580,7 @@ nsresult nsPluginHost::FindPlugins(PRBool aCreatePluginList, PRBool * aPluginsCh
|
|||
// if we are just looking for possible changes,
|
||||
// no need to proceed if changes are detected
|
||||
if (!aCreatePluginList && *aPluginsChanged) {
|
||||
mCachedPlugins = nsnull;
|
||||
NS_ITERATIVE_UNREF_LIST(nsRefPtr<nsPluginTag>, mCachedPlugins, mNext);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
@ -4608,7 +4606,7 @@ nsresult nsPluginHost::FindPlugins(PRBool aCreatePluginList, PRBool * aPluginsCh
|
|||
// if we are just looking for possible changes,
|
||||
// no need to proceed if changes are detected
|
||||
if (!aCreatePluginList && *aPluginsChanged) {
|
||||
mCachedPlugins = nsnull;
|
||||
NS_ITERATIVE_UNREF_LIST(nsRefPtr<nsPluginTag>, mCachedPlugins, mNext);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
@ -4656,7 +4654,7 @@ nsresult nsPluginHost::FindPlugins(PRBool aCreatePluginList, PRBool * aPluginsCh
|
|||
// if we are just looking for possible changes,
|
||||
// no need to proceed if changes are detected
|
||||
if (!aCreatePluginList && *aPluginsChanged) {
|
||||
mCachedPlugins = nsnull;
|
||||
NS_ITERATIVE_UNREF_LIST(nsRefPtr<nsPluginTag>, mCachedPlugins, mNext);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
@ -4683,7 +4681,7 @@ nsresult nsPluginHost::FindPlugins(PRBool aCreatePluginList, PRBool * aPluginsCh
|
|||
|
||||
// if we are not creating the list, there is no need to proceed
|
||||
if (!aCreatePluginList) {
|
||||
mCachedPlugins = nsnull;
|
||||
NS_ITERATIVE_UNREF_LIST(nsRefPtr<nsPluginTag>, mCachedPlugins, mNext);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -4693,7 +4691,7 @@ nsresult nsPluginHost::FindPlugins(PRBool aCreatePluginList, PRBool * aPluginsCh
|
|||
WritePluginInfo();
|
||||
|
||||
// No more need for cached plugins. Clear it up.
|
||||
mCachedPlugins = nsnull;
|
||||
NS_ITERATIVE_UNREF_LIST(nsRefPtr<nsPluginTag>, mCachedPlugins, mNext);
|
||||
|
||||
// reverse our list of plugins
|
||||
nsRefPtr<nsPluginTag> next;
|
||||
|
@ -4717,7 +4715,7 @@ nsPluginHost::UpdatePluginInfo(nsPluginTag* aPluginTag)
|
|||
{
|
||||
ReadPluginInfo();
|
||||
WritePluginInfo();
|
||||
mCachedPlugins = nsnull;
|
||||
NS_ITERATIVE_UNREF_LIST(nsRefPtr<nsPluginTag>, mCachedPlugins, mNext);
|
||||
|
||||
if (!aPluginTag || aPluginTag->IsEnabled())
|
||||
return NS_OK;
|
||||
|
|
Загрузка…
Ссылка в новой задаче