Make the nsPluginInstanceTag destructor non-recursive to avoid exhausting stack space. b=486349 r+sr=jst

This commit is contained in:
Mats Palmgren 2009-08-19 02:25:36 +02:00
Родитель de45d635f7
Коммит 3db17e0fb0
1 изменённых файлов: 42 добавлений и 44 удалений

Просмотреть файл

@ -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;