Bug 325229 part 1 - standalone glue registers exit routine which is called after module unload; also fixes bug 317481 - C API for nsTraceRefcnt; also fixes bug 318622 - Make nsTraceRefcntImpl::SetActivityIsLegal work properly and turn it on; design review by dbaron, r=darin

git-svn-id: svn://10.0.0.236/trunk@189558 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
benjamin%smedbergs.us 2006-02-10 15:00:36 +00:00
parent ca08a4fcea
commit 70d82c362b
23 changed files with 1205 additions and 1156 deletions

View File

@ -5728,18 +5728,6 @@ else
AC_DEFINE(MOZ_LOGGING)
fi
dnl ========================================================
dnl Crash on assert
dnl ========================================================
MOZ_ARG_ENABLE_BOOL(crash-on-assert,
[ --enable-crash-on-assert
Make NS_ASSERTION crash on Unix],
_CRASH_ON_ASSERT=1,
_CRASH_ON_ASSERT= )
if test "$_CRASH_ON_ASSERT"; then
AC_DEFINE(UNIX_CRASH_ON_ASSERT)
fi
dnl ========================================================
dnl = Enable function reordering. Off by default
dnl ========================================================

View File

@ -181,7 +181,7 @@ private:
#define NS_BOX_ASSERTION(box,expr,str) \
if (!(expr)) { \
box->DumpBox(stdout); \
NSGlue_Assertion(str, #expr, __FILE__, __LINE__); \
NS_DebugBreak(NSDebugAssertion, str, #expr, __FILE__, __LINE__); \
}
#else
#define NS_BOX_ASSERTION(box,expr,str) {}

View File

@ -746,22 +746,28 @@ static void DumpArbitraryHelp()
{
nsresult rv;
nsXREDirProvider dirProvider;
dirProvider.Initialize(nsnull);
NS_LogInit();
ScopedXPCOMStartup xpcom;
xpcom.Initialize();
xpcom.DoAutoreg();
{
nsXREDirProvider dirProvider;
dirProvider.Initialize(nsnull);
nsCOMPtr<nsICommandLineRunner> cmdline
(do_CreateInstance("@mozilla.org/toolkit/command-line;1"));
if (!cmdline)
return;
ScopedXPCOMStartup xpcom;
xpcom.Initialize();
xpcom.DoAutoreg();
nsCString text;
rv = cmdline->GetHelpText(text);
if (NS_SUCCEEDED(rv))
printf("%s", text.get());
nsCOMPtr<nsICommandLineRunner> cmdline
(do_CreateInstance("@mozilla.org/toolkit/command-line;1"));
if (!cmdline)
return;
nsCString text;
rv = cmdline->GetHelpText(text);
if (NS_SUCCEEDED(rv))
printf("%s", text.get());
}
NS_LogTerm();
}
// English text needs to go into a dtd file.
@ -1950,443 +1956,449 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
gArgc = argc = NS_TraceMallocStartupArgs(argc, argv);
#endif
nsXREDirProvider dirProvider;
NS_LogInit();
{
nsXREDirProvider dirProvider;
rv = dirProvider.Initialize(gAppData->directory);
if (NS_FAILED(rv))
return 1;
}
// Check for -register, which registers chrome and then exits immediately.
if (CheckArg("register")) {
ScopedXPCOMStartup xpcom;
rv = xpcom.Initialize();
NS_ENSURE_SUCCESS(rv, 1);
// Check for -register, which registers chrome and then exits immediately.
if (CheckArg("register")) {
ScopedXPCOMStartup xpcom;
rv = xpcom.Initialize();
NS_ENSURE_SUCCESS(rv, 1);
{
nsCOMPtr<nsIChromeRegistry> chromeReg
(do_GetService("@mozilla.org/chrome/chrome-registry;1"));
NS_ENSURE_TRUE(chromeReg, 1);
{
nsCOMPtr<nsIChromeRegistry> chromeReg
(do_GetService("@mozilla.org/chrome/chrome-registry;1"));
NS_ENSURE_TRUE(chromeReg, 1);
chromeReg->CheckForNewChrome();
chromeReg->CheckForNewChrome();
}
return 0;
}
return 0;
}
#if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_GTK2)
// setup for private colormap. Ideally we'd like to do this
// in nsAppShell::Create, but we need to get in before gtk
// has been initialized to make sure everything is running
// consistently.
if (CheckArg("install"))
gdk_rgb_set_install(TRUE);
// setup for private colormap. Ideally we'd like to do this
// in nsAppShell::Create, but we need to get in before gtk
// has been initialized to make sure everything is running
// consistently.
if (CheckArg("install"))
gdk_rgb_set_install(TRUE);
// Initialize GTK+1/2 here for splash
// Initialize GTK+1/2 here for splash
#if defined(MOZ_WIDGET_GTK)
gtk_set_locale();
gtk_set_locale();
#endif
gtk_init(&gArgc, &gArgv);
gtk_init(&gArgc, &gArgv);
#if defined(MOZ_WIDGET_GTK2)
// g_set_application_name () is only defined in glib2.2 and higher.
PRLibrary *glib2 = nsnull;
_g_set_application_name_fn _g_set_application_name =
// g_set_application_name () is only defined in glib2.2 and higher.
PRLibrary *glib2 = nsnull;
_g_set_application_name_fn _g_set_application_name =
(_g_set_application_name_fn)PR_FindFunctionSymbolAndLibrary("g_set_application_name", &glib2);
if (_g_set_application_name) {
_g_set_application_name(gAppData->name);
}
if (glib2) {
PR_UnloadLibrary(glib2);
}
if (_g_set_application_name) {
_g_set_application_name(gAppData->name);
}
if (glib2) {
PR_UnloadLibrary(glib2);
}
#endif
gtk_widget_set_default_visual(gdk_rgb_get_visual());
gtk_widget_set_default_colormap(gdk_rgb_get_cmap());
gtk_widget_set_default_visual(gdk_rgb_get_visual());
gtk_widget_set_default_colormap(gdk_rgb_get_cmap());
#endif /* MOZ_WIDGET_GTK || MOZ_WIDGET_GTK2 */
#if defined(MOZ_WIDGET_QT)
QApplication qapp(argc, argv);
QApplication qapp(argc, argv);
#endif
// #if defined(MOZ_WIDGET_XLIB)
// XXXtimeless fix me! How do we get a Display from here to nsAppShell.cpp ?
// #endif
// #if defined(MOZ_WIDGET_XLIB)
// XXXtimeless fix me! How do we get a Display from here to nsAppShell.cpp ?
// #endif
// Call the code to install our handler
// Call the code to install our handler
#ifdef MOZ_JPROF
setupProfilingStuff();
setupProfilingStuff();
#endif
// Try to allocate "native app support."
nsCOMPtr<nsINativeAppSupport> nativeApp;
rv = NS_CreateNativeAppSupport(getter_AddRefs(nativeApp));
if (NS_FAILED(rv))
return 1;
// Try to allocate "native app support."
nsCOMPtr<nsINativeAppSupport> nativeApp;
rv = NS_CreateNativeAppSupport(getter_AddRefs(nativeApp));
if (NS_FAILED(rv))
return 1;
PRBool canRun = PR_FALSE;
rv = nativeApp->Start(&canRun);
if (NS_FAILED(rv) || !canRun) {
return 1;
}
PRBool canRun = PR_FALSE;
rv = nativeApp->Start(&canRun);
if (NS_FAILED(rv) || !canRun) {
return 1;
}
#ifdef MOZ_XPINSTALL
//----------------------------------------------------------------
// We need to check if a previous installation occured and
// if so, make sure it finished and cleaned up correctly.
//
// If there is an xpicleanup.dat file left around, that means the
// previous installation did not finish correctly. We must cleanup
// before a valid mozilla can run.
//
// Show the user a platform-specific Alert message, then spawn the
// xpicleanup utility, then exit.
//----------------------------------------------------------------
nsCOMPtr<nsIFile> registryFile;
rv = dirProvider.GetAppDir()->Clone(getter_AddRefs(registryFile));
if (NS_SUCCEEDED(rv)) {
registryFile->AppendNative(CLEANUP_REGISTRY);
//----------------------------------------------------------------
// We need to check if a previous installation occured and
// if so, make sure it finished and cleaned up correctly.
//
// If there is an xpicleanup.dat file left around, that means the
// previous installation did not finish correctly. We must cleanup
// before a valid mozilla can run.
//
// Show the user a platform-specific Alert message, then spawn the
// xpicleanup utility, then exit.
//----------------------------------------------------------------
{
nsCOMPtr<nsIFile> registryFile;
rv = dirProvider.GetAppDir()->Clone(getter_AddRefs(registryFile));
if (NS_SUCCEEDED(rv)) {
registryFile->AppendNative(CLEANUP_REGISTRY);
PRBool exists;
rv = registryFile->Exists(&exists);
if (NS_SUCCEEDED(rv) && exists) {
return VerifyInstallation(dirProvider.GetAppDir());
PRBool exists;
rv = registryFile->Exists(&exists);
if (NS_SUCCEEDED(rv) && exists) {
return VerifyInstallation(dirProvider.GetAppDir());
}
}
}
}
#endif
#ifdef MOZ_ENABLE_XREMOTE
// handle -remote now that xpcom is fired up
// handle -remote now that xpcom is fired up
const char* xremotearg;
ArgResult ar = CheckArg("remote", &xremotearg);
if (ar == ARG_BAD) {
PR_fprintf(PR_STDERR, "Error: -remote requires an argument\n");
return 1;
}
if (ar) {
return HandleRemoteArgument(xremotearg);
}
const char* xremotearg;
ArgResult ar = CheckArg("remote", &xremotearg);
if (ar == ARG_BAD) {
PR_fprintf(PR_STDERR, "Error: -remote requires an argument\n");
return 1;
}
if (ar) {
return HandleRemoteArgument(xremotearg);
}
if (!PR_GetEnv("MOZ_NO_REMOTE")) {
// Try to remote the entire command line. If this fails, start up normally.
if (RemoteCommandLine())
return 0;
}
if (!PR_GetEnv("MOZ_NO_REMOTE")) {
// Try to remote the entire command line. If this fails, start up normally.
if (RemoteCommandLine())
return 0;
}
#endif
#if defined(MOZ_UPDATER)
// Check for and process any available updates
ProcessUpdates(dirProvider.GetAppDir(), gRestartArgc, gRestartArgv);
// Check for and process any available updates
ProcessUpdates(dirProvider.GetAppDir(), gRestartArgc, gRestartArgv);
#endif
nsCOMPtr<nsIProfileLock> profileLock;
PRBool startOffline = PR_FALSE;
nsCOMPtr<nsIProfileLock> profileLock;
PRBool startOffline = PR_FALSE;
rv = SelectProfile(getter_AddRefs(profileLock), nativeApp, &startOffline);
if (rv == NS_ERROR_LAUNCHED_CHILD_PROCESS ||
rv == NS_ERROR_ABORT) return 0;
if (NS_FAILED(rv)) return 1;
rv = SelectProfile(getter_AddRefs(profileLock), nativeApp, &startOffline);
if (rv == NS_ERROR_LAUNCHED_CHILD_PROCESS ||
rv == NS_ERROR_ABORT) return 0;
if (NS_FAILED(rv)) return 1;
nsCOMPtr<nsILocalFile> profD;
rv = profileLock->GetDirectory(getter_AddRefs(profD));
NS_ENSURE_SUCCESS(rv, 1);
nsCOMPtr<nsILocalFile> profLD;
rv = profileLock->GetLocalDirectory(getter_AddRefs(profLD));
NS_ENSURE_SUCCESS(rv, 1);
rv = dirProvider.SetProfile(profD, profLD);
NS_ENSURE_SUCCESS(rv, 1);
//////////////////////// NOW WE HAVE A PROFILE ////////////////////////
PRBool upgraded = PR_FALSE;
nsCAutoString version;
BuildVersion(version);
// Check for version compatibility with the last version of the app this
// profile was started with. The format of the version stamp is defined
// by the BuildVersion function.
PRBool versionOK = CheckCompatibility(profD, version,
dirProvider.GetGREDir(),
gAppData->directory);
// Every time a profile is loaded by a build with a different version,
// it updates the compatibility.ini file saying what version last wrote
// the compreg.dat. On subsequent launches if the version matches,
// there is no need for re-registration. If the user loads the same
// profile in different builds the component registry must be
// re-generated to prevent mysterious component loading failures.
//
if (gSafeMode) {
RemoveComponentRegistries(profD, profLD, PR_FALSE);
WriteVersion(profD, NS_LITERAL_CSTRING("Safe Mode"),
dirProvider.GetGREDir(), gAppData->directory);
}
else if (versionOK) {
if (ComponentsListChanged(profD)) {
// Remove compreg.dat and xpti.dat, forcing component re-registration.
// The new list of additional components directories is derived from
// information in "extensions.ini".
RemoveComponentRegistries(profD, profLD, PR_FALSE);
}
// Nothing need be done for the normal startup case.
}
else {
// Remove compreg.dat and xpti.dat, forcing component re-registration
// with the default set of components (this disables any potentially
// troublesome incompatible XPCOM components).
RemoveComponentRegistries(profD, profLD, PR_TRUE);
// Tell the Extension Manager it should check for incompatible
// Extensions and re-write the "extensions.ini" file with a list of
// directories for compatible extensions
upgraded = PR_TRUE;
// Write out version
WriteVersion(profD, version,
dirProvider.GetGREDir(), gAppData->directory);
}
PRBool needsRestart = PR_FALSE;
PRBool appInitiatedRestart = PR_FALSE;
// Allows the user to forcefully bypass the restart process at their
// own risk. Useful for debugging or for tinderboxes where child
// processes can be problematic.
{
// Start the real application
ScopedXPCOMStartup xpcom;
rv = xpcom.Initialize();
NS_ENSURE_SUCCESS(rv, 1);
rv = xpcom.DoAutoreg();
rv |= xpcom.InitEventQueue();
rv |= xpcom.SetWindowCreator(nativeApp);
nsCOMPtr<nsILocalFile> profD;
rv = profileLock->GetDirectory(getter_AddRefs(profD));
NS_ENSURE_SUCCESS(rv, 1);
{
if (startOffline) {
nsCOMPtr<nsIIOService> io (do_GetService("@mozilla.org/network/io-service;1"));
NS_ENSURE_TRUE(io, 1);
io->SetOffline(PR_TRUE);
nsCOMPtr<nsILocalFile> profLD;
rv = profileLock->GetLocalDirectory(getter_AddRefs(profLD));
NS_ENSURE_SUCCESS(rv, 1);
rv = dirProvider.SetProfile(profD, profLD);
NS_ENSURE_SUCCESS(rv, 1);
//////////////////////// NOW WE HAVE A PROFILE ////////////////////////
PRBool upgraded = PR_FALSE;
nsCAutoString version;
BuildVersion(version);
// Check for version compatibility with the last version of the app this
// profile was started with. The format of the version stamp is defined
// by the BuildVersion function.
PRBool versionOK = CheckCompatibility(profD, version,
dirProvider.GetGREDir(),
gAppData->directory);
// Every time a profile is loaded by a build with a different version,
// it updates the compatibility.ini file saying what version last wrote
// the compreg.dat. On subsequent launches if the version matches,
// there is no need for re-registration. If the user loads the same
// profile in different builds the component registry must be
// re-generated to prevent mysterious component loading failures.
//
if (gSafeMode) {
RemoveComponentRegistries(profD, profLD, PR_FALSE);
WriteVersion(profD, NS_LITERAL_CSTRING("Safe Mode"),
dirProvider.GetGREDir(), gAppData->directory);
}
else if (versionOK) {
if (ComponentsListChanged(profD)) {
// Remove compreg.dat and xpti.dat, forcing component re-registration.
// The new list of additional components directories is derived from
// information in "extensions.ini".
RemoveComponentRegistries(profD, profLD, PR_FALSE);
}
// Nothing need be done for the normal startup case.
}
else {
// Remove compreg.dat and xpti.dat, forcing component re-registration
// with the default set of components (this disables any potentially
// troublesome incompatible XPCOM components).
RemoveComponentRegistries(profD, profLD, PR_TRUE);
// Tell the Extension Manager it should check for incompatible
// Extensions and re-write the "extensions.ini" file with a list of
// directories for compatible extensions
upgraded = PR_TRUE;
// Write out version
WriteVersion(profD, version,
dirProvider.GetGREDir(), gAppData->directory);
}
PRBool needsRestart = PR_FALSE;
PRBool appInitiatedRestart = PR_FALSE;
// Allows the user to forcefully bypass the restart process at their
// own risk. Useful for debugging or for tinderboxes where child
// processes can be problematic.
{
// Start the real application
ScopedXPCOMStartup xpcom;
rv = xpcom.Initialize();
NS_ENSURE_SUCCESS(rv, 1);
rv = xpcom.DoAutoreg();
rv |= xpcom.InitEventQueue();
rv |= xpcom.SetWindowCreator(nativeApp);
NS_ENSURE_SUCCESS(rv, 1);
{
NS_TIMELINE_ENTER("startupNotifier");
nsCOMPtr<nsIObserver> startupNotifier
(do_CreateInstance(NS_APPSTARTUPNOTIFIER_CONTRACTID, &rv));
NS_ENSURE_SUCCESS(rv, 1);
if (startOffline) {
nsCOMPtr<nsIIOService> io (do_GetService("@mozilla.org/network/io-service;1"));
NS_ENSURE_TRUE(io, 1);
io->SetOffline(PR_TRUE);
}
startupNotifier->Observe(nsnull, APPSTARTUP_TOPIC, nsnull);
NS_TIMELINE_LEAVE("startupNotifier");
}
{
NS_TIMELINE_ENTER("startupNotifier");
nsCOMPtr<nsIObserver> startupNotifier
(do_CreateInstance(NS_APPSTARTUPNOTIFIER_CONTRACTID, &rv));
NS_ENSURE_SUCCESS(rv, 1);
nsCOMPtr<nsIAppStartup> appStartup
(do_GetService(NS_APPSTARTUP_CONTRACTID));
NS_ENSURE_TRUE(appStartup, 1);
startupNotifier->Observe(nsnull, APPSTARTUP_TOPIC, nsnull);
NS_TIMELINE_LEAVE("startupNotifier");
}
if (gDoMigration) {
nsCOMPtr<nsIFile> file;
profD->Clone(getter_AddRefs(file));
file->AppendNative(NS_LITERAL_CSTRING("override.ini"));
nsINIParser parser;
nsCOMPtr<nsILocalFile> localFile(do_QueryInterface(file));
nsresult rv = parser.Init(localFile);
if (NS_SUCCEEDED(rv)) {
nsCAutoString buf;
rv = parser.GetString("XRE", "EnableProfileMigrator", buf);
nsCOMPtr<nsIAppStartup> appStartup
(do_GetService(NS_APPSTARTUP_CONTRACTID));
NS_ENSURE_TRUE(appStartup, 1);
if (gDoMigration) {
nsCOMPtr<nsIFile> file;
profD->Clone(getter_AddRefs(file));
file->AppendNative(NS_LITERAL_CSTRING("override.ini"));
nsINIParser parser;
nsCOMPtr<nsILocalFile> localFile(do_QueryInterface(file));
nsresult rv = parser.Init(localFile);
if (NS_SUCCEEDED(rv)) {
if (buf[0] == '0' || buf[0] == 'f' || buf[0] == 'F') {
gDoMigration = PR_FALSE;
nsCAutoString buf;
rv = parser.GetString("XRE", "EnableProfileMigrator", buf);
if (NS_SUCCEEDED(rv)) {
if (buf[0] == '0' || buf[0] == 'f' || buf[0] == 'F') {
gDoMigration = PR_FALSE;
}
}
}
}
}
// Profile Migration
if (gAppData->flags & NS_XRE_ENABLE_PROFILE_MIGRATOR && gDoMigration) {
gDoMigration = PR_FALSE;
nsCOMPtr<nsIProfileMigrator> pm
(do_CreateInstance(NS_PROFILEMIGRATOR_CONTRACTID));
if (pm)
pm->Migrate(&dirProvider);
}
dirProvider.DoStartup();
nsCOMPtr<nsICommandLineRunner> cmdLine
(do_CreateInstance("@mozilla.org/toolkit/command-line;1"));
NS_ENSURE_TRUE(cmdLine, 1);
nsCOMPtr<nsIFile> workingDir;
rv = NS_GetSpecialDirectory(NS_OS_CURRENT_WORKING_DIR, getter_AddRefs(workingDir));
NS_ENSURE_SUCCESS(rv, 1);
rv = cmdLine->Init(gArgc, gArgv,
workingDir, nsICommandLine::STATE_INITIAL_LAUNCH);
NS_ENSURE_SUCCESS(rv, 1);
/* Special-case services that need early access to the command
line. */
nsCOMPtr<nsIObserver> chromeObserver
(do_GetService("@mozilla.org/chrome/chrome-registry;1"));
if (chromeObserver) {
chromeObserver->Observe(cmdLine, "command-line-startup", nsnull);
}
NS_TIMELINE_ENTER("appStartup->CreateHiddenWindow");
rv = appStartup->CreateHiddenWindow();
NS_TIMELINE_LEAVE("appStartup->CreateHiddenWindow");
NS_ENSURE_SUCCESS(rv, 1);
// Extension Compatibility Checking and Startup
if (gAppData->flags & NS_XRE_ENABLE_EXTENSION_MANAGER) {
nsCOMPtr<nsIExtensionManager> em(do_GetService("@mozilla.org/extensions/manager;1"));
NS_ENSURE_TRUE(em, 1);
if (CheckArg("install-global-extension") || CheckArg("install-global-theme")) {
// Do the required processing and then shut down.
em->HandleCommandLineArgs(cmdLine);
return 0;
// Profile Migration
if (gAppData->flags & NS_XRE_ENABLE_PROFILE_MIGRATOR && gDoMigration) {
gDoMigration = PR_FALSE;
nsCOMPtr<nsIProfileMigrator> pm
(do_CreateInstance(NS_PROFILEMIGRATOR_CONTRACTID));
if (pm)
pm->Migrate(&dirProvider);
}
dirProvider.DoStartup();
if (upgraded) {
rv = em->CheckForMismatches(&needsRestart);
if (NS_FAILED(rv)) {
needsRestart = PR_FALSE;
upgraded = PR_FALSE;
}
}
if (!upgraded || !needsRestart)
em->Start(cmdLine, &needsRestart);
}
// We want to restart no more than 2 times. The first restart,
// NO_EM_RESTART == "0" , and the second time, "1".
char* noEMRestart = PR_GetEnv("NO_EM_RESTART");
if (noEMRestart && *noEMRestart && *noEMRestart == '1') {
if (upgraded || needsRestart) {
NS_WARNING("EM tried to force us to restart twice! Forcefully preventing that.");
}
needsRestart = upgraded = PR_FALSE;
}
if (!upgraded && !needsRestart) {
SaveStateForAppInitiatedRestart();
// clear out any environment variables which may have been set
// during the relaunch process now that we know we won't be relaunching.
PR_SetEnv("XRE_PROFILE_PATH=");
PR_SetEnv("XRE_PROFILE_LOCAL_PATH=");
PR_SetEnv("XRE_START_OFFLINE=");
PR_SetEnv("XRE_IMPORT_PROFILES=");
PR_SetEnv("NO_EM_RESTART=");
PR_SetEnv("XUL_APP_FILE=");
PR_SetEnv("XRE_BINARY_PATH=");
#ifdef XP_MACOSX
// we re-initialize the command-line service and do appleevents munging
// after we are sure that we're not restarting
cmdLine = do_CreateInstance("@mozilla.org/toolkit/command-line;1");
nsCOMPtr<nsICommandLineRunner> cmdLine
(do_CreateInstance("@mozilla.org/toolkit/command-line;1"));
NS_ENSURE_TRUE(cmdLine, 1);
rv = InitializeMacCommandLine(gArgc, gArgv);
nsCOMPtr<nsIFile> workingDir;
rv = NS_GetSpecialDirectory(NS_OS_CURRENT_WORKING_DIR, getter_AddRefs(workingDir));
NS_ENSURE_SUCCESS(rv, 1);
rv = cmdLine->Init(gArgc, gArgv,
workingDir, nsICommandLine::STATE_INITIAL_LAUNCH);
NS_ENSURE_SUCCESS(rv, 1);
#endif
nsCOMPtr<nsIObserverService> obsService
(do_GetService("@mozilla.org/observer-service;1"));
if (obsService)
obsService->NotifyObservers(nsnull, "final-ui-startup", nsnull);
rv = cmdLine->Run();
NS_ENSURE_SUCCESS_LOG(rv, 1);
/* Special-case services that need early access to the command
line. */
nsCOMPtr<nsIObserver> chromeObserver
(do_GetService("@mozilla.org/chrome/chrome-registry;1"));
if (chromeObserver) {
chromeObserver->Observe(cmdLine, "command-line-startup", nsnull);
}
NS_TIMELINE_ENTER("appStartup->CreateHiddenWindow");
rv = appStartup->CreateHiddenWindow();
NS_TIMELINE_LEAVE("appStartup->CreateHiddenWindow");
NS_ENSURE_SUCCESS(rv, 1);
// Extension Compatibility Checking and Startup
if (gAppData->flags & NS_XRE_ENABLE_EXTENSION_MANAGER) {
nsCOMPtr<nsIExtensionManager> em(do_GetService("@mozilla.org/extensions/manager;1"));
NS_ENSURE_TRUE(em, 1);
if (CheckArg("install-global-extension") || CheckArg("install-global-theme")) {
// Do the required processing and then shut down.
em->HandleCommandLineArgs(cmdLine);
return 0;
}
if (upgraded) {
rv = em->CheckForMismatches(&needsRestart);
if (NS_FAILED(rv)) {
needsRestart = PR_FALSE;
upgraded = PR_FALSE;
}
}
if (!upgraded || !needsRestart)
em->Start(cmdLine, &needsRestart);
}
// We want to restart no more than 2 times. The first restart,
// NO_EM_RESTART == "0" , and the second time, "1".
char* noEMRestart = PR_GetEnv("NO_EM_RESTART");
if (noEMRestart && *noEMRestart && *noEMRestart == '1') {
if (upgraded || needsRestart) {
NS_WARNING("EM tried to force us to restart twice! Forcefully preventing that.");
}
needsRestart = upgraded = PR_FALSE;
}
if (!upgraded && !needsRestart) {
SaveStateForAppInitiatedRestart();
// clear out any environment variables which may have been set
// during the relaunch process now that we know we won't be relaunching.
PR_SetEnv("XRE_PROFILE_PATH=");
PR_SetEnv("XRE_PROFILE_LOCAL_PATH=");
PR_SetEnv("XRE_START_OFFLINE=");
PR_SetEnv("XRE_IMPORT_PROFILES=");
PR_SetEnv("NO_EM_RESTART=");
PR_SetEnv("XUL_APP_FILE=");
PR_SetEnv("XRE_BINARY_PATH=");
#ifdef XP_MACOSX
// we re-initialize the command-line service and do appleevents munging
// after we are sure that we're not restarting
cmdLine = do_CreateInstance("@mozilla.org/toolkit/command-line;1");
NS_ENSURE_TRUE(cmdLine, 1);
rv = InitializeMacCommandLine(gArgc, gArgv);
NS_ENSURE_SUCCESS(rv, 1);
rv = cmdLine->Init(gArgc, gArgv,
workingDir, nsICommandLine::STATE_INITIAL_LAUNCH);
NS_ENSURE_SUCCESS(rv, 1);
#endif
nsCOMPtr<nsIObserverService> obsService
(do_GetService("@mozilla.org/observer-service;1"));
if (obsService)
obsService->NotifyObservers(nsnull, "final-ui-startup", nsnull);
rv = cmdLine->Run();
NS_ENSURE_SUCCESS_LOG(rv, 1);
#ifdef MOZ_ENABLE_XREMOTE
// if we have X remote support, start listening for requests on the
// proxy window.
nsCOMPtr<nsIRemoteService> remoteService;
remoteService = do_GetService("@mozilla.org/toolkit/remote-service;1");
if (remoteService)
remoteService->Startup(gAppData->name, nsnull);
// if we have X remote support, start listening for requests on the
// proxy window.
nsCOMPtr<nsIRemoteService> remoteService;
remoteService = do_GetService("@mozilla.org/toolkit/remote-service;1");
if (remoteService)
remoteService->Startup(gAppData->name, nsnull);
#endif /* MOZ_ENABLE_XREMOTE */
// enable win32 DDE responses and Mac appleevents responses
nativeApp->Enable();
// enable win32 DDE responses and Mac appleevents responses
nativeApp->Enable();
NS_TIMELINE_ENTER("appStartup->Run");
rv = appStartup->Run();
NS_TIMELINE_LEAVE("appStartup->Run");
if (NS_FAILED(rv)) {
NS_ERROR("failed to run appstartup");
gLogConsoleErrors = PR_TRUE;
}
NS_TIMELINE_ENTER("appStartup->Run");
rv = appStartup->Run();
NS_TIMELINE_LEAVE("appStartup->Run");
if (NS_FAILED(rv)) {
NS_ERROR("failed to run appstartup");
gLogConsoleErrors = PR_TRUE;
}
// Check for an application initiated restart. This is one that
// corresponds to nsIAppStartup.quit(eRestart)
if (rv == NS_SUCCESS_RESTART_APP) {
needsRestart = PR_TRUE;
appInitiatedRestart = PR_TRUE;
}
// Check for an application initiated restart. This is one that
// corresponds to nsIAppStartup.quit(eRestart)
if (rv == NS_SUCCESS_RESTART_APP) {
needsRestart = PR_TRUE;
appInitiatedRestart = PR_TRUE;
}
#ifdef MOZ_ENABLE_XREMOTE
// shut down the x remote proxy window
if (remoteService)
remoteService->Shutdown();
// shut down the x remote proxy window
if (remoteService)
remoteService->Shutdown();
#endif /* MOZ_ENABLE_XREMOTE */
#ifdef MOZ_TIMELINE
// Make sure we print this out even if timeline is runtime disabled
if (NS_FAILED(NS_TIMELINE_LEAVE("main1")))
NS_TimelineForceMark("...main1");
// Make sure we print this out even if timeline is runtime disabled
if (NS_FAILED(NS_TIMELINE_LEAVE("main1")))
NS_TimelineForceMark("...main1");
#endif
}
else {
// Upgrade condition (build id changes), but the restart hint was
// not set by the Extension Manager. This is because the compatibility
// resolution for Extensions is different than for the component
// registry - major milestone vs. build id.
needsRestart = PR_TRUE;
}
}
profileLock->Unlock();
}
// Restart the app after XPCOM has been shut down cleanly.
if (needsRestart) {
if (appInitiatedRestart) {
RestoreStateForAppInitiatedRestart();
}
else {
// Upgrade condition (build id changes), but the restart hint was
// not set by the Extension Manager. This is because the compatibility
// resolution for Extensions is different than for the component
// registry - major milestone vs. build id.
needsRestart = PR_TRUE;
char* noEMRestart = PR_GetEnv("NO_EM_RESTART");
if (noEMRestart && *noEMRestart) {
PR_SetEnv("NO_EM_RESTART=1");
}
else {
PR_SetEnv("NO_EM_RESTART=0");
}
}
}
profileLock->Unlock();
}
// Restart the app after XPCOM has been shut down cleanly.
if (needsRestart) {
if (appInitiatedRestart) {
RestoreStateForAppInitiatedRestart();
}
else {
char* noEMRestart = PR_GetEnv("NO_EM_RESTART");
if (noEMRestart && *noEMRestart) {
PR_SetEnv("NO_EM_RESTART=1");
}
else {
PR_SetEnv("NO_EM_RESTART=0");
}
}
// Ensure that these environment variables are set:
SaveFileToEnvIfUnset("XRE_PROFILE_PATH", profD);
SaveFileToEnvIfUnset("XRE_PROFILE_LOCAL_PATH", profLD);
// Ensure that these environment variables are set:
SaveFileToEnvIfUnset("XRE_PROFILE_PATH", profD);
SaveFileToEnvIfUnset("XRE_PROFILE_LOCAL_PATH", profLD);
#ifdef XP_MACOSX
if (gBinaryPath) {
static char kEnvVar[MAXPATHLEN];
sprintf(kEnvVar, "XRE_BINARY_PATH=%s", gBinaryPath);
PR_SetEnv(kEnvVar);
}
if (gBinaryPath) {
static char kEnvVar[MAXPATHLEN];
sprintf(kEnvVar, "XRE_BINARY_PATH=%s", gBinaryPath);
PR_SetEnv(kEnvVar);
}
#endif
rv = LaunchChild(nativeApp, appInitiatedRestart);
return rv == NS_ERROR_LAUNCHED_CHILD_PROCESS ? 0 : 1;
rv = LaunchChild(nativeApp, appInitiatedRestart);
return rv == NS_ERROR_LAUNCHED_CHILD_PROCESS ? 0 : 1;
}
}
NS_LogTerm();
return NS_FAILED(rv) ? 1 : 0;
}

View File

@ -22,6 +22,7 @@
* Contributor(s):
* IBM Corp.
* Henry Sobotka
* Benjamin Smedberg <benjamin@smedbergs.us>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -46,6 +47,7 @@
#include "nsError.h"
#include "prerror.h"
#include "prerr.h"
#include "prenv.h"
#if defined(XP_BEOS)
/* For DEBUGGER macros */
@ -57,42 +59,33 @@
#include <stdlib.h>
#endif
#if defined(XP_UNIX) && !defined(UNIX_CRASH_ON_ASSERT)
#include <signal.h>
/* for nsTraceRefcnt::WalkTheStack() */
#include "nsISupportsUtils.h"
#include "nsTraceRefcntImpl.h"
#include "nsISupportsUtils.h"
#if defined(__GNUC__) && (defined(__i386) || defined(__x86_64__))
# define DebugBreak() { asm("int $3"); }
#elif defined(__APPLE__) && defined(TARGET_CARBON)
# include "MacTypes.h"
# define DebugBreak() { Debugger(); }
#else
# define DebugBreak()
#if defined(XP_UNIX)
#include <signal.h>
#endif
static void
Abort(const char *aMsg);
static void
Break(const char *aMsg);
#if defined(__APPLE__) && defined(TARGET_CARBON)
# include "MacTypes.h"
#endif
#if defined(XP_OS2)
/* Added definitions for DebugBreak() for 2 different OS/2 compilers. Doing
* the int3 on purpose so that a developer can step over the
* instruction if so desired. Not always possible if trapping due to exception
* handling IBM-AKR
*/
#define INCL_WINDIALOGS // need for WinMessageBox
#include <os2.h>
#include <string.h>
#if defined(DEBUG)
#define DebugBreak() { asm("int $3"); }
#else
#define DebugBreak()
#endif /* DEBUG */
# define INCL_WINDIALOGS // need for WinMessageBox
# include <os2.h>
# include <string.h>
#endif /* XP_OS2 */
#if defined(_WIN32)
#include <windows.h>
#include <signal.h>
#include <malloc.h> // for _alloca
#elif defined(XP_UNIX)
#include <stdlib.h>
#endif
@ -129,10 +122,47 @@ PRBool InDebugger()
#endif /* WIN32*/
NS_IMPL_THREADSAFE_ISUPPORTS1(nsDebugImpl, nsIDebug)
NS_IMPL_QUERY_INTERFACE1(nsDebugImpl, nsIDebug)
nsDebugImpl::nsDebugImpl()
NS_IMETHODIMP_(nsrefcnt)
nsDebugImpl::AddRef()
{
return 2;
}
NS_IMETHODIMP_(nsrefcnt)
nsDebugImpl::Release()
{
return 1;
}
NS_IMETHODIMP
nsDebugImpl::Assertion(const char *aStr, const char *aExpr,
const char *aFile, PRInt32 aLine)
{
NS_DebugBreak(NS_DEBUG_ASSERTION, aStr, aExpr, aFile, aLine);
return NS_OK;
}
NS_IMETHODIMP
nsDebugImpl::Warning(const char *aStr, const char *aFile, PRInt32 aLine)
{
NS_DebugBreak(NS_DEBUG_WARNING, aStr, nsnull, aFile, aLine);
return NS_OK;
}
NS_IMETHODIMP
nsDebugImpl::Break(const char *aFile, PRInt32 aLine)
{
NS_DebugBreak(NS_DEBUG_BREAK, nsnull, nsnull, aFile, aLine);
return NS_OK;
}
NS_IMETHODIMP
nsDebugImpl::Abort(const char *aFile, PRInt32 aLine)
{
NS_DebugBreak(NS_DEBUG_ABORT, nsnull, nsnull, aFile, aLine);
return NS_OK;
}
/**
@ -150,275 +180,296 @@ static void InitLog(void)
}
}
enum nsAssertBehavior {
NS_ASSERT_UNINITIALIZED,
NS_ASSSERT_WARN,
NS_ASSSERT_SUSPEND,
NS_ASSSERT_STACK,
NS_ASSSERT_TRAP,
NS_ASSSERT_ABORT
};
static nsAssertBehavior GetAssertBehavior()
{
static nsAssertBehavior gAssertBehavior = NS_ASSERT_UNINITIALIZED;
if (gAssertBehavior != NS_ASSERT_UNINITIALIZED)
return gAssertBehavior;
NS_IMETHODIMP
nsDebugImpl::Assertion(const char *aStr, const char *aExpr, const char *aFile, PRInt32 aLine)
#if defined(XP_WIN) || defined(XP_OS2)
gAssertBehavior = NS_ASSSERT_TRAP;
#else
gAssertBehavior = NS_ASSSERT_WARN;
#endif
const char *assertString = PR_GetEnv("XPCOM_DEBUG_BREAK");
if (!assertString || !*assertString)
return gAssertBehavior;
if (!strcmp(assertString, "warn"))
return gAssertBehavior = NS_ASSSERT_WARN;
if (!strcmp(assertString, "suspend"))
return gAssertBehavior = NS_ASSSERT_SUSPEND;
if (!strcmp(assertString, "stack"))
return gAssertBehavior = NS_ASSSERT_STACK;
if (!strcmp(assertString, "abort"))
return gAssertBehavior = NS_ASSSERT_ABORT;
if (!strcmp(assertString, "trap") || !strcmp(assertString, "break"))
return gAssertBehavior = NS_ASSSERT_TRAP;
fprintf(stderr, "Unrecognized value of XPCOM_DEBUG_BREAK\n");
return gAssertBehavior;
}
struct FixedBuffer
{
FixedBuffer() : curlen(0) { buffer[0] = '\0'; }
char buffer[1000];
PRUint32 curlen;
};
static PRIntn
StuffFixedBuffer(void *closure, const char *buf, PRUint32 len)
{
FixedBuffer *fb = (FixedBuffer*) closure;
// strip the trailing null, we add it again later
if (buf[len - 1] == '\0')
--len;
if (fb->curlen + len >= sizeof(fb->buffer))
len = sizeof(fb->buffer) - fb->curlen - 1;
if (len) {
memcpy(fb->buffer + fb->curlen, buf, len);
fb->curlen += len;
fb->buffer[fb->curlen] = '\0';
}
return len;
}
EXPORT_XPCOM_API(void)
NS_DebugBreak(PRUint32 aSeverity, const char *aStr, const char *aExpr,
const char *aFile, PRInt32 aLine)
{
InitLog();
char buf[1000];
PR_snprintf(buf, sizeof(buf),
"###!!! ASSERTION: %s: '%s', file %s, line %d",
aStr, aExpr, aFile, aLine);
FixedBuffer buf;
PRLogModuleLevel ll = PR_LOG_WARNING;
const char *sevString = "WARNING";
switch (aSeverity) {
case NS_DEBUG_ASSERTION:
sevString = "\07###!!! ASSERTION";
ll = PR_LOG_ERROR;
break;
case NS_DEBUG_BREAK:
sevString = "\07###!!! BREAK";
ll = PR_LOG_ALWAYS;
break;
case NS_DEBUG_ABORT:
sevString = "\07###!!! ABORT";
ll = PR_LOG_ALWAYS;
break;
default:
aSeverity = NS_DEBUG_WARNING;
};
PR_sxprintf(StuffFixedBuffer, &buf, "%s: ", sevString);
if (aStr)
PR_sxprintf(StuffFixedBuffer, &buf, "%s: ", aStr);
if (aExpr)
PR_sxprintf(StuffFixedBuffer, &buf, "'%s', ", aExpr);
if (aFile)
PR_sxprintf(StuffFixedBuffer, &buf, "file %s, ", aFile);
if (aLine != -1)
PR_sxprintf(StuffFixedBuffer, &buf, "line %d", aLine);
// Write out the assertion message to the debug log
PR_LOG(gDebugLog, PR_LOG_ERROR, ("%s", buf));
PR_LOG(gDebugLog, ll, ("%s", buf.buffer));
PR_LogFlush();
// And write it out to the stderr
fprintf(stderr, "%s\n", buf);
fprintf(stderr, "%s\n", buf.buffer);
fflush(stderr);
#if defined(_WIN32)
char* assertBehavior = getenv("XPCOM_DEBUG_BREAK");
if (assertBehavior && strcmp(assertBehavior, "warn") == 0)
return NS_OK;
switch (aSeverity) {
case NS_DEBUG_WARNING:
return;
#ifndef WINCE // we really just want to crash for now
static int ignoreDebugger;
if (!ignoreDebugger) {
const char *shouldIgnoreDebugger = getenv("XPCOM_DEBUG_DLG");
ignoreDebugger = 1 + (shouldIgnoreDebugger && !strcmp(shouldIgnoreDebugger, "1"));
case NS_DEBUG_BREAK:
Break(buf.buffer);
return;
case NS_DEBUG_ABORT:
Abort(buf.buffer);
return;
}
if((ignoreDebugger == 2) || !InDebugger())
{
DWORD code = IDRETRY;
/* Create the debug dialog out of process to avoid the crashes caused by
* Windows events leaking into our event loop from an in process dialog.
* We do this by launching windbgdlg.exe (built in xpcom/windbgdlg).
* See http://bugzilla.mozilla.org/show_bug.cgi?id=54792
*/
PROCESS_INFORMATION pi;
STARTUPINFO si;
char executable[MAX_PATH];
char* pName;
// Now we deal with assertions
memset(&pi, 0, sizeof(pi));
switch (GetAssertBehavior()) {
case NS_ASSSERT_WARN:
return;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
si.wShowWindow = SW_SHOW;
if(GetModuleFileName(GetModuleHandle("xpcom.dll"), executable, MAX_PATH) &&
NULL != (pName = strrchr(executable, '\\')) &&
NULL != strcpy(pName+1, "windbgdlg.exe") &&
#ifdef DEBUG_jband
(printf("Launching %s\n", executable), PR_TRUE) &&
#endif
CreateProcess(executable, buf, NULL, NULL, PR_FALSE,
DETACHED_PROCESS | NORMAL_PRIORITY_CLASS,
NULL, NULL, &si, &pi) &&
WAIT_OBJECT_0 == WaitForSingleObject(pi.hProcess, INFINITE) &&
GetExitCodeProcess(pi.hProcess, &code))
{
CloseHandle(pi.hProcess);
}
switch(code)
{
case IDABORT:
//This should exit us
raise(SIGABRT);
//If we are ignored exit this way..
_exit(3);
break;
case IDIGNORE:
return NS_OK;
// Fall Through
}
}
#endif // WINCE
#endif
#if defined(XP_OS2)
char* assertBehavior = getenv("XPCOM_DEBUG_BREAK");
if (assertBehavior && strcmp(assertBehavior, "warn") == 0)
return NS_OK;
char msg[1200];
PR_snprintf(msg, sizeof(msg),
"%s\n\nClick Cancel to Debug Application.\n"
"Click Enter to continue running the Application.", buf);
ULONG code = MBID_ERROR;
code = WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, msg,
"NSGlue_Assertion", 0,
MB_ERROR | MB_ENTERCANCEL);
/* It is possible that we are executing on a thread that doesn't have a
* message queue. In that case, the message won't appear, and code will
* be 0xFFFF. We'll give the user a chance to debug it by calling
* Break()
* Actually, that's a really bad idea since this happens a lot with threadsafe
* assertions and since it means that you can't actually run the debug build
* outside a debugger without it crashing constantly.
*/
if(( code == MBID_ENTER ) || (code == MBID_ERROR))
{
return NS_OK;
// If Retry, Fall Through
}
#endif
Break(aFile, aLine);
return NS_OK;
}
NS_IMETHODIMP
nsDebugImpl::Break(const char *aFile, PRInt32 aLine)
{
#ifndef TEMP_MAC_HACK
// Write out the assertion message to the debug log
InitLog();
PR_LOG(gDebugLog, PR_LOG_ERROR,
("###!!! Break: at file %s, line %d", aFile, aLine));
PR_LogFlush();
fprintf(stderr, "Break: at file %s, line %d\n",aFile, aLine); fflush(stderr);
fflush(stderr);
#if defined(_WIN32)
#ifdef _M_IX86
::DebugBreak();
#endif
#elif defined(XP_UNIX) && !defined(UNIX_CRASH_ON_ASSERT)
fprintf(stderr, "\07");
char *assertBehavior = getenv("XPCOM_DEBUG_BREAK");
if (!assertBehavior) {
// the default; nothing else to do
;
} else if ( strcmp(assertBehavior, "suspend")== 0 ) {
// the suspend case is first because we wanna send the signal before
// other threads have had a chance to get too far from the state that
// caused this assertion (in case they happen to have been involved).
//
case NS_ASSSERT_SUSPEND:
#ifdef XP_UNIX
fprintf(stderr, "Suspending process; attach with the debugger.\n");
kill(0, SIGSTOP);
} else if ( strcmp(assertBehavior, "warn")==0 ) {
// same as default; nothing else to do (see "suspend" case comment for
// why this compare isn't done as part of the default case)
//
;
}
else if ( strcmp(assertBehavior,"stack")==0 ) {
// walk the stack
//
nsTraceRefcntImpl::WalkTheStack(stderr);
}
else if ( strcmp(assertBehavior,"abort")==0 ) {
// same as UNIX_CRASH_ON_ASSERT
//
Abort(aFile, aLine);
} else if ( strcmp(assertBehavior,"trap")==0 ) {
DebugBreak();
} else {
fprintf(stderr, "unrecognized value of XPCOM_DEBUG_BREAK env var!\n");
}
fflush(stderr); // this shouldn't really be necessary, i don't think,
// but maybe there's some lame stdio that buffers stderr
#elif defined(XP_BEOS)
{
#ifdef UNIX_CRASH_ON_ASSERT
char buf[2000];
sprintf(buf, "Break: at file %s, line %d", aFile, aLine);
DEBUGGER(buf);
#endif
}
#else
Abort(aFile, aLine);
Break(buf.buffer);
#endif
#endif // TEMP_MAC_HACK
return NS_OK;
return;
case NS_ASSSERT_STACK:
nsTraceRefcntImpl::WalkTheStack(stderr);
return;
case NS_ASSSERT_ABORT:
Abort(buf.buffer);
return;
case NS_ASSSERT_TRAP:
Break(buf.buffer);
}
}
NS_IMETHODIMP
nsDebugImpl::Abort(const char *aFile, PRInt32 aLine)
static void
Abort(const char *aMsg)
{
InitLog();
PR_LOG(gDebugLog, PR_LOG_ERROR,
("###!!! Abort: at file %s, line %d", aFile, aLine));
PR_LogFlush();
fprintf(stderr, "\07 Abort\n"); fflush(stderr);
fflush(stderr);
#if defined(_WIN32)
#ifdef _M_IX86
long* __p = (long*) 0x7;
*__p = 0x7;
#else /* _M_ALPHA */
PR_Abort();
#endif
//This should exit us
raise(SIGABRT);
//If we are ignored exit this way..
_exit(3);
#elif defined(XP_UNIX)
PR_Abort();
#elif defined(XP_OS2)
DebugBreak();
return NS_OK;
#elif defined(XP_BEOS)
{
#ifndef DEBUG_cls
char buf[2000];
sprintf(buf, "Abort: at file %s, line %d", aFile, aLine);
DEBUGGER(buf);
DEBUGGER(aMsg);
#endif
}
}
#else
// Don't know how to abort on this platform! call Break() instead
Break(aMsg);
#endif
return NS_OK;
}
NS_IMETHODIMP
nsDebugImpl::Warning(const char* aMessage,
const char* aFile, PRIntn aLine)
// Abort() calls this function, don't call it!
static void
Break(const char *aMsg)
{
InitLog();
#if defined(_WIN32)
#ifndef WINCE // we really just want to crash for now
static int ignoreDebugger;
if (!ignoreDebugger) {
const char *shouldIgnoreDebugger = getenv("XPCOM_DEBUG_DLG");
ignoreDebugger = 1 + (shouldIgnoreDebugger && !strcmp(shouldIgnoreDebugger, "1"));
}
if((ignoreDebugger == 2) || !InDebugger()) {
DWORD code = IDRETRY;
char buf[1000];
PR_snprintf(buf, sizeof(buf),
"WARNING: %s, file %s, line %d",
aMessage, aFile, aLine);
/* Create the debug dialog out of process to avoid the crashes caused by
* Windows events leaking into our event loop from an in process dialog.
* We do this by launching windbgdlg.exe (built in xpcom/windbgdlg).
* See http://bugzilla.mozilla.org/show_bug.cgi?id=54792
*/
PROCESS_INFORMATION pi;
STARTUPINFO si;
char executable[MAX_PATH];
char* pName;
// Write out the warning message to the debug log
PR_LOG(gDebugLog, PR_LOG_ERROR, ("%s", buf));
memset(&pi, 0, sizeof(pi));
// And write it out to the stdout
fprintf(stderr, "%s\n", buf);
fflush(stderr);
return NS_OK;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
si.wShowWindow = SW_SHOW;
// 2nd arg of CreateProcess is in/out
char *msgCopy = (char*) _alloca(strlen(aMsg) + 1);
strcpy(msgCopy, aMsg);
if(GetModuleFileName(GetModuleHandle("xpcom.dll"), executable, MAX_PATH) &&
NULL != (pName = strrchr(executable, '\\')) &&
NULL != strcpy(pName+1, "windbgdlg.exe") &&
CreateProcess(executable, msgCopy, NULL, NULL, PR_FALSE,
DETACHED_PROCESS | NORMAL_PRIORITY_CLASS,
NULL, NULL, &si, &pi) &&
WAIT_OBJECT_0 == WaitForSingleObject(pi.hProcess, INFINITE) &&
GetExitCodeProcess(pi.hProcess, &code)) {
CloseHandle(pi.hProcess);
}
switch(code) {
case IDABORT:
//This should exit us
raise(SIGABRT);
//If we are ignored exit this way..
_exit(3);
case IDIGNORE:
return;
}
}
::DebugBreak();
#endif // WINCE
#elif defined(XP_OS2)
char msg[1200];
PR_snprintf(msg, sizeof(msg),
"%s\n\nClick Cancel to Debug Application.\n"
"Click Enter to continue running the Application.", aMsg);
ULONG code = MBID_ERROR;
code = WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, msg,
"NSGlue_Assertion", 0,
MB_ERROR | MB_ENTERCANCEL);
/* It is possible that we are executing on a thread that doesn't have a
* message queue. In that case, the message won't appear, and code will
* be 0xFFFF. We'll give the user a chance to debug it by calling
* Break()
* Actually, that's a really bad idea since this happens a lot with threadsafe
* assertions and since it means that you can't actually run the debug build
* outside a debugger without it crashing constantly.
*/
if (( code == MBID_ENTER ) || (code == MBID_ERROR))
return;
asm("int $3");
#elif defined(XP_BEOS)
DEBUGGER(aMgr);
#elif defined(__GNUC__) && (defined(__i386) || defined(__x86_64__))
asm("int $3");
#elif defined(__APPLE__) && defined(TARGET_CARBON)
Debugger();
#else
// don't know how to break on this platform
#endif
}
static const nsDebugImpl kImpl;
NS_METHOD
nsDebugImpl::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
{
*aInstancePtr = nsnull;
nsIDebug* debug = new nsDebugImpl();
if (!debug)
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = debug->QueryInterface(aIID, aInstancePtr);
if (NS_FAILED(rv)) {
delete debug;
}
return rv;
NS_ENSURE_NO_AGGREGATION(outer);
return NS_CONST_CAST(nsDebugImpl*, &kImpl)->
QueryInterface(aIID, aInstancePtr);
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -42,11 +42,7 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSIDEBUG
nsDebugImpl();
static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
private:
~nsDebugImpl() {}
};

View File

@ -38,12 +38,8 @@
#include "nsISupports.idl"
/**
* nsIDebug is an interface between XPCOM Glue and XPCOM. Users should access
* the nsIDebug interface through the static class nsDebug.
* @see nsDebug.h
*
* @status UNDER_REVIEW
*
* @status DEPRECATED Replaced by the NS_DebugBreak function.
* @status FROZEN
*/
[scriptable, uuid(3bf0c3d7-3bd9-4cf2-a971-33572c503e1e)]

View File

@ -57,20 +57,6 @@
{ 0x00000000, 0x0000, 0x0000, \
{0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} }
/**
* Reference count values
*
* This is the return type for AddRef() and Release() in nsISupports.
* IUnknown of COM returns an unsigned long from equivalent functions.
* The following ifdef exists to maintain binary compatibility with
* IUnknown.
*/
#if defined(XP_WIN) && PR_BYTES_PER_LONG == 4
typedef unsigned long nsrefcnt;
#else
typedef PRUint32 nsrefcnt;
#endif
/**
* Basic component object model interface. Objects which implement
* this interface support runtime interface discovery (QueryInterface)

View File

@ -38,11 +38,10 @@
#include "nsISupports.idl"
/**
* nsITraceRefcnt is an interface between XPCOM Glue and XPCOM. Users should
* access the nsITraceRefcnt interface through the static class nsTraceRefcnt.
* @see nsTraceRefcnt.h
*
* @status UNDER_REVIEW
* nsITraceRefcnt is an interface between XPCOM Glue and XPCOM.
*
* @status DEPRECATED Replaced by the NS_Log* functions.
* @status FROZEN
*/
[uuid(273dc92f-0fe6-4545-96a9-21be77828039)]

View File

@ -469,10 +469,10 @@ DumpStackToFile(FILE* aStream)
walkerThread = ::CreateThread( NULL, 0, DumpStackToFileThread, (LPVOID) &data, 0, NULL ) ;
if (walkerThread) {
walkerReturn = ::WaitForSingleObject(walkerThread, 2000); // no timeout is never a good idea
CloseHandle(myThread) ;
if (walkerReturn != WAIT_OBJECT_0) {
PrintError("ThreadWait", aStream);
}
CloseHandle(myThread);
}
else {
PrintError("ThreadCreate", aStream);

View File

@ -79,11 +79,13 @@ NS_MeanAndStdDev(double n, double sumOfValues, double sumOfSquaredValues,
////////////////////////////////////////////////////////////////////////////////
#define NS_IMPL_REFCNT_LOGGING
#ifdef WINCE
#undef NS_BUILD_REFCNT_LOGGING
#undef NS_IMPL_REFCNT_LOGGING
#endif
#ifdef NS_BUILD_REFCNT_LOGGING
#ifdef NS_IMPL_REFCNT_LOGGING
#include "plhash.h"
#include "prmem.h"
@ -107,13 +109,22 @@ static PRBool gLogLeaksOnly;
static void (*leakyLogAddRef)(void* p, int oldrc, int newrc);
static void (*leakyLogRelease)(void* p, int oldrc, int newrc);
static PRBool gInitialized = PR_FALSE;
#define BAD_TLS_INDEX ((PRUintn) -1)
// if gActivityTLS == BAD_TLS_INDEX, then we're
// unitialized... otherwise this points to a NSPR TLS thread index
// indicating whether addref activity is legal. If the PTR_TO_INT32 is 0 then
// activity is ok, otherwise not!
static PRUintn gActivityTLS = BAD_TLS_INDEX;
static PRBool gInitialized;
static nsrefcnt gInitCount;
static FILE *gBloatLog = nsnull;
static FILE *gRefcntsLog = nsnull;
static FILE *gAllocLog = nsnull;
static FILE *gLeakyLog = nsnull;
static FILE *gCOMPtrLog = nsnull;
static PRBool gActivityIsLegal = PR_FALSE;
struct serialNumberRecord {
PRInt32 serialNumber;
@ -132,15 +143,11 @@ struct nsTraceRefcntStats {
double mObjsOutstandingSquared;
};
#ifdef DEBUG_dbaron_off
// I hope to turn this on for everybody once we hit it a little less.
#define ASSERT_ACTIVITY_IS_LEGAL \
NS_WARN_IF_FALSE(gActivityIsLegal, \
"XPCOM objects created/destroyed from static ctor/dtor")
#else
#define ASSERT_ACTIVITY_IS_LEGAL
#endif
#define ASSERT_ACTIVITY_IS_LEGAL \
NS_WARN_IF_FALSE(gActivityTLS != BAD_TLS_INDEX && \
NS_PTR_TO_INT32(PR_GetThreadPrivate(gActivityTLS)) == 0, \
"XPCOM objects created/destroyed from static ctor/dtor");
// These functions are copied from nsprpub/lib/ds/plhash.c, with changes
// to the functions not called Default* to free the serialNumberRecord or
@ -445,13 +452,13 @@ static PRIntn PR_CALLBACK DumpSerialNumbers(PLHashEntry* aHashEntry, PRIntn aInd
}
#endif /* NS_BUILD_REFCNT_LOGGING */
#endif /* NS_IMPL_REFCNT_LOGGING */
NS_COM nsresult
nsTraceRefcntImpl::DumpStatistics(StatisticsType type, FILE* out)
{
nsresult rv = NS_OK;
#ifdef NS_BUILD_REFCNT_LOGGING
#ifdef NS_IMPL_REFCNT_LOGGING
if (gBloatLog == nsnull || gBloatView == nsnull) {
return NS_ERROR_FAILURE;
}
@ -527,7 +534,7 @@ done:
NS_COM void
nsTraceRefcntImpl::ResetStatistics()
{
#ifdef NS_BUILD_REFCNT_LOGGING
#ifdef NS_IMPL_REFCNT_LOGGING
LOCK_TRACELOG();
if (gBloatView) {
PL_HashTableDestroy(gBloatView);
@ -537,7 +544,7 @@ nsTraceRefcntImpl::ResetStatistics()
#endif
}
#ifdef NS_BUILD_REFCNT_LOGGING
#ifdef NS_IMPL_REFCNT_LOGGING
static PRBool LogThisType(const char* aTypeName)
{
void* he = PL_HashTableLookup(gTypesToLog, aTypeName);
@ -873,7 +880,7 @@ NS_COM void
nsTraceRefcntImpl::LoadLibrarySymbols(const char* aLibraryName,
void* aLibrayHandle)
{
#ifdef NS_BUILD_REFCNT_LOGGING
#ifdef NS_IMPL_REFCNT_LOGGING
#if defined(_WIN32) && defined(_M_IX86) /* Win32 x86 only */
if (!gInitialized)
InitTraceLog();
@ -928,44 +935,37 @@ nsTraceRefcntImpl::LoadLibrarySymbols(const char* aLibraryName,
//----------------------------------------------------------------------
// don't use the logging ones. :-)
NS_IMETHODIMP_(nsrefcnt) nsTraceRefcntImpl::AddRef(void)
EXPORT_XPCOM_API(void)
NS_LogInit()
{
NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt");
++mRefCnt;
return mRefCnt;
#ifdef NS_IMPL_REFCNT_LOGGING
if (++gInitCount)
nsTraceRefcntImpl::SetActivityIsLegal(PR_TRUE);
#endif
}
NS_IMETHODIMP_(nsrefcnt) nsTraceRefcntImpl::Release(void)
{
NS_PRECONDITION(0 != mRefCnt, "dup release");
--mRefCnt;
if (mRefCnt == 0) {
mRefCnt = 1; /* stabilize */
delete this;
return 0;
EXPORT_XPCOM_API(void)
NS_LogTerm()
{
NS_ASSERTION(gInitCount > 0,
"NS_LogTerm without matching NS_LogInit");
if (--gInitCount == 0) {
nsTraceRefcntImpl::DumpStatistics();
nsTraceRefcntImpl::ResetStatistics();
nsTraceRefcntImpl::Shutdown();
#ifdef NS_IMPL_REFCNT_LOGGING
nsTraceRefcntImpl::SetActivityIsLegal(PR_FALSE);
gActivityTLS = BAD_TLS_INDEX;
#endif
}
return mRefCnt;
}
NS_IMPL_QUERY_INTERFACE1(nsTraceRefcntImpl, nsITraceRefcnt)
nsTraceRefcntImpl::nsTraceRefcntImpl()
EXPORT_XPCOM_API(void)
NS_LogAddRef(void* aPtr, nsrefcnt aRefcnt,
const char* aClazz, PRUint32 classSize)
{
/* member initializers and constructor code */
}
NS_IMETHODIMP
nsTraceRefcntImpl::LogAddRef(void* aPtr,
nsrefcnt aRefcnt,
const char* aClazz,
PRUint32 classSize)
{
#ifdef NS_BUILD_REFCNT_LOGGING
#ifdef NS_IMPL_REFCNT_LOGGING
ASSERT_ACTIVITY_IS_LEGAL;
if (!gInitialized)
InitTraceLog();
@ -996,7 +996,7 @@ nsTraceRefcntImpl::LogAddRef(void* aPtr,
if (aRefcnt == 1 && gAllocLog && loggingThisType && loggingThisObject) {
fprintf(gAllocLog, "\n<%s> 0x%08X %d Create\n",
aClazz, NS_PTR_TO_INT32(aPtr), serialno);
WalkTheStack(gAllocLog);
nsTraceRefcntImpl::WalkTheStack(gAllocLog);
}
if (gRefcntsLog && loggingThisType && loggingThisObject) {
@ -1007,22 +1007,19 @@ nsTraceRefcntImpl::LogAddRef(void* aPtr,
// Can't use PR_LOG(), b/c it truncates the line
fprintf(gRefcntsLog,
"\n<%s> 0x%08X %d AddRef %d\n", aClazz, NS_PTR_TO_INT32(aPtr), serialno, aRefcnt);
WalkTheStack(gRefcntsLog);
nsTraceRefcntImpl::WalkTheStack(gRefcntsLog);
fflush(gRefcntsLog);
}
}
UNLOCK_TRACELOG();
}
#endif
return NS_OK;
}
NS_IMETHODIMP
nsTraceRefcntImpl::LogRelease(void* aPtr,
nsrefcnt aRefcnt,
const char* aClazz)
EXPORT_XPCOM_API(void)
NS_LogRelease(void* aPtr, nsrefcnt aRefcnt, const char* aClazz)
{
#ifdef NS_BUILD_REFCNT_LOGGING
#ifdef NS_IMPL_REFCNT_LOGGING
ASSERT_ACTIVITY_IS_LEGAL;
if (!gInitialized)
InitTraceLog();
@ -1055,7 +1052,7 @@ nsTraceRefcntImpl::LogRelease(void* aPtr,
// Can't use PR_LOG(), b/c it truncates the line
fprintf(gRefcntsLog,
"\n<%s> 0x%08X %d Release %d\n", aClazz, NS_PTR_TO_INT32(aPtr), serialno, aRefcnt);
WalkTheStack(gRefcntsLog);
nsTraceRefcntImpl::WalkTheStack(gRefcntsLog);
fflush(gRefcntsLog);
}
}
@ -1067,7 +1064,7 @@ nsTraceRefcntImpl::LogRelease(void* aPtr,
fprintf(gAllocLog,
"\n<%s> 0x%08X %d Destroy\n",
aClazz, NS_PTR_TO_INT32(aPtr), serialno);
WalkTheStack(gAllocLog);
nsTraceRefcntImpl::WalkTheStack(gAllocLog);
}
if (aRefcnt == 0 && gSerialNumbers && loggingThisType) {
@ -1077,15 +1074,12 @@ nsTraceRefcntImpl::LogRelease(void* aPtr,
UNLOCK_TRACELOG();
}
#endif
return NS_OK;
}
NS_IMETHODIMP
nsTraceRefcntImpl::LogCtor(void* aPtr,
const char* aType,
PRUint32 aInstanceSize)
EXPORT_XPCOM_API(void)
NS_LogCtor(void* aPtr, const char* aType, PRUint32 aInstanceSize)
{
#ifdef NS_BUILD_REFCNT_LOGGING
#ifdef NS_IMPL_REFCNT_LOGGING
ASSERT_ACTIVITY_IS_LEGAL;
if (!gInitialized)
InitTraceLog();
@ -1110,22 +1104,19 @@ nsTraceRefcntImpl::LogCtor(void* aPtr,
if (gAllocLog && loggingThisType && loggingThisObject) {
fprintf(gAllocLog, "\n<%s> 0x%08X %d Ctor (%d)\n",
aType, NS_PTR_TO_INT32(aPtr), serialno, aInstanceSize);
WalkTheStack(gAllocLog);
nsTraceRefcntImpl::WalkTheStack(gAllocLog);
}
UNLOCK_TRACELOG();
}
#endif
return NS_OK;
}
NS_IMETHODIMP
nsTraceRefcntImpl::LogDtor(void* aPtr,
const char* aType,
PRUint32 aInstanceSize)
EXPORT_XPCOM_API(void)
NS_LogDtor(void* aPtr, const char* aType, PRUint32 aInstanceSize)
{
#ifdef NS_BUILD_REFCNT_LOGGING
#ifdef NS_IMPL_REFCNT_LOGGING
ASSERT_ACTIVITY_IS_LEGAL;
if (!gInitialized)
InitTraceLog();
@ -1154,21 +1145,19 @@ nsTraceRefcntImpl::LogDtor(void* aPtr,
if (gAllocLog && loggingThisType && loggingThisObject) {
fprintf(gAllocLog, "\n<%s> 0x%08X %d Dtor (%d)\n",
aType, NS_PTR_TO_INT32(aPtr), serialno, aInstanceSize);
WalkTheStack(gAllocLog);
nsTraceRefcntImpl::WalkTheStack(gAllocLog);
}
UNLOCK_TRACELOG();
}
#endif
return NS_OK;
}
NS_IMETHODIMP
nsTraceRefcntImpl::LogAddCOMPtr(void* aCOMPtr,
nsISupports* aObject)
EXPORT_XPCOM_API(void)
NS_LogCOMPtrAddRef(void* aCOMPtr, nsISupports* aObject)
{
#if defined(NS_BUILD_REFCNT_LOGGING) && defined(HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR)
#if defined(NS_IMPL_REFCNT_LOGGING) && defined(HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR)
// Get the most-derived object.
void *object = dynamic_cast<void *>(aObject);
@ -1176,11 +1165,11 @@ nsTraceRefcntImpl::LogAddCOMPtr(void* aCOMPtr,
// of the object being logged. If we're logging a specific type,
// then
if (!gTypesToLog || !gSerialNumbers) {
return NS_OK;
return;
}
PRInt32 serialno = GetSerialNumber(object, PR_FALSE);
if (serialno == 0) {
return NS_OK;
return;
}
if (!gInitialized)
@ -1197,21 +1186,19 @@ nsTraceRefcntImpl::LogAddCOMPtr(void* aCOMPtr,
if (gCOMPtrLog && loggingThisObject) {
fprintf(gCOMPtrLog, "\n<?> 0x%08X %d nsCOMPtrAddRef %d 0x%08X\n",
NS_PTR_TO_INT32(object), serialno, count?(*count):-1, NS_PTR_TO_INT32(aCOMPtr));
WalkTheStack(gCOMPtrLog);
nsTraceRefcntImpl::WalkTheStack(gCOMPtrLog);
}
UNLOCK_TRACELOG();
}
#endif
return NS_OK;
}
NS_IMETHODIMP
nsTraceRefcntImpl::LogReleaseCOMPtr(void* aCOMPtr,
nsISupports* aObject)
EXPORT_XPCOM_API(void)
NS_LogCOMPtrRelease(void* aCOMPtr, nsISupports* aObject)
{
#if defined(NS_BUILD_REFCNT_LOGGING) && defined(HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR)
#if defined(NS_IMPL_REFCNT_LOGGING) && defined(HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR)
// Get the most-derived object.
void *object = dynamic_cast<void *>(aObject);
@ -1219,11 +1206,11 @@ nsTraceRefcntImpl::LogReleaseCOMPtr(void* aCOMPtr,
// of the object being logged. If we're logging a specific type,
// then
if (!gTypesToLog || !gSerialNumbers) {
return NS_OK;
return;
}
PRInt32 serialno = GetSerialNumber(object, PR_FALSE);
if (serialno == 0) {
return NS_OK;
return;
}
if (!gInitialized)
@ -1240,27 +1227,23 @@ nsTraceRefcntImpl::LogReleaseCOMPtr(void* aCOMPtr,
if (gCOMPtrLog && loggingThisObject) {
fprintf(gCOMPtrLog, "\n<?> 0x%08X %d nsCOMPtrRelease %d 0x%08X\n",
NS_PTR_TO_INT32(object), serialno, count?(*count):-1, NS_PTR_TO_INT32(aCOMPtr));
WalkTheStack(gCOMPtrLog);
nsTraceRefcntImpl::WalkTheStack(gCOMPtrLog);
}
UNLOCK_TRACELOG();
}
#endif
return NS_OK;
}
NS_COM void
nsTraceRefcntImpl::Startup()
{
#ifdef NS_BUILD_REFCNT_LOGGING
SetActivityIsLegal(PR_TRUE);
#endif
}
NS_COM void
nsTraceRefcntImpl::Shutdown()
{
#ifdef NS_BUILD_REFCNT_LOGGING
#ifdef NS_IMPL_REFCNT_LOGGING
if (gBloatView) {
PL_HashTableDestroy(gBloatView);
@ -1278,33 +1261,81 @@ nsTraceRefcntImpl::Shutdown()
PL_HashTableDestroy(gSerialNumbers);
gSerialNumbers = nsnull;
}
SetActivityIsLegal(PR_FALSE);
#endif
}
NS_COM void
nsTraceRefcntImpl::SetActivityIsLegal(PRBool aLegal)
{
#ifdef NS_BUILD_REFCNT_LOGGING
gActivityIsLegal = aLegal;
#ifdef NS_IMPL_REFCNT_LOGGING
if (gActivityTLS == BAD_TLS_INDEX)
PR_NewThreadPrivateIndex(&gActivityTLS, nsnull);
PR_SetThreadPrivate(gActivityTLS, NS_INT32_TO_PTR(!aLegal));
#endif
}
NS_IMPL_QUERY_INTERFACE1(nsTraceRefcntImpl, nsITraceRefcnt)
NS_IMETHODIMP_(nsrefcnt) nsTraceRefcntImpl::AddRef(void)
{
return 2;
}
NS_IMETHODIMP_(nsrefcnt) nsTraceRefcntImpl::Release(void)
{
return 1;
}
NS_IMETHODIMP
nsTraceRefcntImpl::LogAddRef(void *aPtr, nsrefcnt aNewRefcnt,
const char *aTypeName, PRUint32 aSize)
{
NS_LogAddRef(aPtr, aNewRefcnt, aTypeName, aSize);
return NS_OK;
}
NS_IMETHODIMP
nsTraceRefcntImpl::LogRelease(void *aPtr, nsrefcnt aNewRefcnt,
const char *aTypeName)
{
NS_LogRelease(aPtr, aNewRefcnt, aTypeName);
return NS_OK;
}
NS_IMETHODIMP
nsTraceRefcntImpl::LogCtor(void *aPtr, const char *aTypeName, PRUint32 aSize)
{
NS_LogCtor(aPtr, aTypeName, aSize);
return NS_OK;
}
NS_IMETHODIMP
nsTraceRefcntImpl::LogDtor(void *aPtr, const char *aTypeName, PRUint32 aSize)
{
NS_LogDtor(aPtr, aTypeName, aSize);
return NS_OK;
}
NS_IMETHODIMP
nsTraceRefcntImpl::LogAddCOMPtr(void *aCOMPtr, nsISupports* aObject)
{
NS_LogCOMPtrAddRef(aCOMPtr, aObject);
return NS_OK;
}
NS_IMETHODIMP
nsTraceRefcntImpl::LogReleaseCOMPtr(void *aCOMPtr, nsISupports* aObject)
{
NS_LogCOMPtrRelease(aCOMPtr, aObject);
return NS_OK;
}
static const nsTraceRefcntImpl kTraceRefcntImpl;
NS_METHOD
nsTraceRefcntImpl::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
{
*aInstancePtr = nsnull;
nsITraceRefcnt* tracer = new nsTraceRefcntImpl();
if (!tracer)
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = tracer->QueryInterface(aIID, aInstancePtr);
if (NS_FAILED(rv)) {
delete tracer;
}
return rv;
return NS_CONST_CAST(nsTraceRefcntImpl*, &kTraceRefcntImpl)->
QueryInterface(aIID, aInstancePtr);
}

View File

@ -47,8 +47,6 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSITRACEREFCNT
nsTraceRefcntImpl();
static NS_COM void Startup();
static NS_COM void Shutdown();
@ -79,9 +77,6 @@ public:
static NS_COM void SetActivityIsLegal(PRBool aLegal);
static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
private:
~nsTraceRefcntImpl() {}
};
#define NS_TRACE_REFCNT_CONTRACTID "@mozilla.org/xpcom/trace-refcnt;1"

View File

@ -241,9 +241,15 @@
* Import/Export macros for XPCOM APIs
*/
#define EXPORT_XPCOM_API(type) extern "C" NS_EXPORT type NS_FROZENCALL
#define IMPORT_XPCOM_API(type) extern "C" NS_IMPORT type NS_FROZENCALL
#define GLUE_XPCOM_API(type) NS_HIDDEN_(type) NS_FROZENCALL
#ifdef __cplusplus
#define EXTERN_C extern "C"
#else
#define EXTERN_C
#endif
#define EXPORT_XPCOM_API(type) EXTERN_C NS_EXPORT type NS_FROZENCALL
#define IMPORT_XPCOM_API(type) EXTERN_C NS_IMPORT type NS_FROZENCALL
#define GLUE_XPCOM_API(type) EXTERN_C NS_HIDDEN_(type) NS_FROZENCALL
#ifdef _IMPL_NS_COM
#define XPCOM_API(type) EXPORT_XPCOM_API(type)
@ -303,6 +309,20 @@
*/
typedef PRUint32 nsresult;
/**
* Reference count values
*
* This is the return type for AddRef() and Release() in nsISupports.
* IUnknown of COM returns an unsigned long from equivalent functions.
* The following ifdef exists to maintain binary compatibility with
* IUnknown.
*/
#if defined(XP_WIN) && PR_BYTES_PER_LONG == 4
typedef unsigned long nsrefcnt;
#else
typedef PRUint32 nsrefcnt;
#endif
/**
* The preferred symbol for null.
*/

View File

@ -39,7 +39,7 @@
#ifndef nsXPCOM_h__
#define nsXPCOM_h__
// Map frozen functions to private symbol names if not using strict API.
/* Map frozen functions to private symbol names if not using strict API. */
#ifdef MOZILLA_INTERNAL_API
# define NS_InitXPCOM2 NS_InitXPCOM2_P
# define NS_InitXPCOM3 NS_InitXPCOM3_P
@ -55,24 +55,40 @@
# define NS_Alloc NS_Alloc_P
# define NS_Realloc NS_Realloc_P
# define NS_Free NS_Free_P
# define NS_DebugBreak NS_DebugBreak_P
# define NS_LogInit NS_LogInit_P
# define NS_LogTerm NS_LogTerm_P
# define NS_LogAddRef NS_LogAddRef_P
# define NS_LogRelease NS_LogRelease_P
# define NS_LogCtor NS_LogCtor_P
# define NS_LogDtor NS_LogDtor_P
# define NS_LogCOMPtrAddRef NS_LogCOMPtrAddRef_P
# define NS_LogCOMPtrRelease NS_LogCOMPtrRelease_P
#endif
#include "nscore.h"
#include "nsXPCOMCID.h"
class nsAString;
class nsACString;
#ifdef __cplusplus
#define DECL_CLASS(c) class c
#else
#define DECL_CLASS(c) typedef struct c c
#endif
class nsIModule;
class nsIComponentManager;
class nsIComponentRegistrar;
class nsIServiceManager;
class nsIFile;
class nsILocalFile;
class nsIDirectoryServiceProvider;
class nsIMemory;
class nsIDebug;
class nsITraceRefcnt;
DECL_CLASS(nsAString);
DECL_CLASS(nsACString);
DECL_CLASS(nsISupports);
DECL_CLASS(nsIModule);
DECL_CLASS(nsIComponentManager);
DECL_CLASS(nsIComponentRegistrar);
DECL_CLASS(nsIServiceManager);
DECL_CLASS(nsIFile);
DECL_CLASS(nsILocalFile);
DECL_CLASS(nsIDirectoryServiceProvider);
DECL_CLASS(nsIMemory);
DECL_CLASS(nsIDebug);
DECL_CLASS(nsITraceRefcnt);
/**
* Every XPCOM component implements this function signature, which is the
@ -130,10 +146,10 @@ NS_InitXPCOM2(nsIServiceManager* *result,
*
* @status FROZEN
*/
struct nsStaticModuleInfo {
typedef struct nsStaticModuleInfo {
const char *name;
nsGetModuleProc getModule;
};
} nsStaticModuleInfo;
/**
* Initialises XPCOM with static components. You must call one of the
@ -274,6 +290,8 @@ NS_GetMemoryManager(nsIMemory* *result);
* other error codes indicate a failure.
*/
#ifdef __cplusplus
XPCOM_API(nsresult)
NS_NewLocalFile(const nsAString &path,
PRBool followLinks,
@ -284,6 +302,8 @@ NS_NewNativeLocalFile(const nsACString &path,
PRBool followLinks,
nsILocalFile* *result);
#endif
/**
* Allocates a block of memory of a particular size. If the memory cannot
* be allocated (because of an out-of-memory condition), null is returned.
@ -331,6 +351,107 @@ NS_Realloc(void* ptr, PRSize size);
XPCOM_API(void)
NS_Free(void* ptr);
/**
* Support for warnings, assertions, and debugging breaks.
*/
enum {
NS_DEBUG_WARNING = 0,
NS_DEBUG_ASSERTION = 1,
NS_DEBUG_BREAK = 2,
NS_DEBUG_ABORT = 3
};
/**
* Print a runtime assertion. This function is available in both debug and
* release builds.
*
* @note Based on the value of aSeverity and the XPCOM_DEBUG_BREAK
* environment variable, this function may cause the application to
* print the warning, print a stacktrace, break into a debugger, or abort
* immediately.
*
* @param aSeverity A NS_DEBUG_* value
* @param aStr A readable error message (ASCII, may be null)
* @param aExpr The expression evaluated (may be null)
* @param aFile The source file containing the assertion (may be null)
* @param aLine The source file line number (-1 indicates no line number)
*/
XPCOM_API(void)
NS_DebugBreak(PRUint32 aSeverity,
const char *aStr, const char *aExpr,
const char *aFile, PRInt32 aLine);
/**
* Perform a stack-walk to a debugging log under various
* circumstances. Used to aid debugging of leaked object graphs.
*
* The NS_Log* functions are available in both debug and release
* builds of XPCOM, but the output will be useless unless binary
* debugging symbols for all modules in the stacktrace are available.
*/
/**
* By default, refcount logging is enabled at NS_InitXPCOM and
* refcount statistics are printed at NS_ShutdownXPCOM. NS_LogInit and
* NS_LogTerm allow applications to enable logging earlier and delay
* printing of logging statistics. They should always be used as a
* matched pair.
*/
XPCOM_API(void)
NS_LogInit();
XPCOM_API(void)
NS_LogTerm();
/**
* Log construction and destruction of objects. Processing tools can use the
* stacktraces printed by these functions to identify objects that are being
* leaked.
*
* @param aPtr A pointer to the concrete object.
* @param aTypeName The class name of the type
* @param aInstanceSize The size of the type
*/
XPCOM_API(void)
NS_LogCtor(void *aPtr, const char *aTypeName, PRUint32 aInstanceSize);
XPCOM_API(void)
NS_LogDtor(void *aPtr, const char *aTypeName, PRUint32 aInstanceSize);
/**
* Log a stacktrace when an XPCOM object's refcount is incremented or
* decremented. Processing tools can use the stacktraces printed by these
* functions to identify objects that were leaked due to XPCOM references.
*
* @param aPtr A pointer to the concrete object
* @param aNewRefCnt The new reference count.
* @param aTypeName The class name of the type
* @param aInstanceSize The size of the type
*/
XPCOM_API(void)
NS_LogAddRef(void *aPtr, nsrefcnt aNewRefCnt,
const char *aTypeName, PRUint32 aInstanceSize);
XPCOM_API(void)
NS_LogRelease(void *aPtr, nsrefcnt aNewRefCnt, const char *aTypeName);
/**
* Log reference counting performed by COMPtrs. Processing tools can
* use the stacktraces printed by these functions to simplify reports
* about leaked objects generated from the data printed by
* NS_LogAddRef/NS_LogRelease.
*
* @param aCOMPtr the address of the COMPtr holding a strong reference
* @param aObject the object being referenced by the COMPtr
*/
XPCOM_API(void)
NS_LogCOMPtrAddRef(void *aCOMPtr, nsISupports *aObject);
XPCOM_API(void)
NS_LogCOMPtrRelease(void *aCOMPtr, nsISupports *aObject);
/**
* Categories (in the category manager service) used by XPCOM:

View File

@ -136,6 +136,16 @@ typedef void* (* AllocFunc)(PRSize size);
typedef void* (* ReallocFunc)(void* ptr, PRSize size);
typedef void (* FreeFunc)(void* ptr);
typedef void (* DebugBreakFunc)(PRUint32 aSeverity,
const char *aStr, const char *aExpr,
const char *aFile, PRInt32 aLine);
typedef void (* xpcomVoidFunc)();
typedef void (* LogAddRefFunc)(void*, nsrefcnt, const char*, PRUint32);
typedef void (* LogReleaseFunc)(void*, nsrefcnt, const char*);
typedef void (* LogCtorFunc)(void*, const char*, PRUint32);
typedef void (* LogCOMPtrFunc)(void*, nsISupports*);
// PRIVATE
typedef nsresult (* RegisterXPCOMExitRoutineFunc)(XPCOMExitRoutine exitRoutine, PRUint32 priority);
typedef nsresult (* UnregisterXPCOMExitRoutineFunc)(XPCOMExitRoutine exitRoutine);
@ -187,6 +197,18 @@ typedef struct XPCOMFunctions{
StringGetMutableDataFunc stringGetMutableData;
CStringGetMutableDataFunc cstringGetMutableData;
Init3Func init3;
// Added for Mozilla 1.9
DebugBreakFunc debugBreakFunc;
xpcomVoidFunc logInitFunc;
xpcomVoidFunc logTermFunc;
LogAddRefFunc logAddRefFunc;
LogReleaseFunc logReleaseFunc;
LogCtorFunc logCtorFunc;
LogCtorFunc logDtorFunc;
LogCOMPtrFunc logCOMPtrAddRefFunc;
LogCOMPtrFunc logCOMPtrReleaseFunc;
} XPCOMFunctions;
typedef nsresult (PR_CALLBACK *GetFrozenFunctionsFunc)(XPCOMFunctions *entryPoints, const char* libraryPath);

View File

@ -421,38 +421,17 @@ static nsIDebug* gDebug = nsnull;
EXPORT_XPCOM_API(nsresult)
NS_GetDebug(nsIDebug** result)
{
nsresult rv = NS_OK;
if (!gDebug)
{
rv = nsDebugImpl::Create(nsnull,
NS_GET_IID(nsIDebug),
(void**)&gDebug);
}
NS_IF_ADDREF(*result = gDebug);
return rv;
return nsDebugImpl::Create(nsnull,
NS_GET_IID(nsIDebug),
(void**) result);
}
#ifdef NS_BUILD_REFCNT_LOGGING
// gTraceRefcnt will be freed during shutdown.
static nsITraceRefcnt* gTraceRefcnt = nsnull;
#endif
EXPORT_XPCOM_API(nsresult)
NS_GetTraceRefcnt(nsITraceRefcnt** result)
{
#ifdef NS_BUILD_REFCNT_LOGGING
nsresult rv = NS_OK;
if (!gTraceRefcnt)
{
rv = nsTraceRefcntImpl::Create(nsnull,
NS_GET_IID(nsITraceRefcnt),
(void**)&gTraceRefcnt);
}
NS_IF_ADDREF(*result = gTraceRefcnt);
return rv;
#else
return NS_ERROR_NOT_INITIALIZED;
#endif
return nsTraceRefcntImpl::Create(nsnull,
NS_GET_IID(nsITraceRefcnt),
(void**) result);
}
EXPORT_XPCOM_API(nsresult)
@ -489,9 +468,7 @@ NS_InitXPCOM3(nsIServiceManager* *result,
// We are not shutting down
gXPCOMShuttingDown = PR_FALSE;
#ifdef NS_BUILD_REFCNT_LOGGING
nsTraceRefcntImpl::Startup();
#endif
NS_LogInit();
// Establish the main thread here.
rv = nsIThread::SetMainThread();
@ -868,11 +845,7 @@ NS_ShutdownXPCOM(nsIServiceManager* servMgr)
NS_IF_RELEASE(gDebug);
#ifdef NS_BUILD_REFCNT_LOGGING
nsTraceRefcntImpl::DumpStatistics();
nsTraceRefcntImpl::ResetStatistics();
nsTraceRefcntImpl::Shutdown();
#endif
NS_LogTerm();
#ifdef GC_LEAK_DETECTOR
// Shutdown the Leak detector.

View File

@ -1,111 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is XPCOM
*
* The Initial Developer of the Original Code is Doug Turner <dougt@meer.net>
*
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsXPCOM.h"
#include "nsXPCOMPrivate.h"
#include "nsCOMPtr.h"
#include "nsIServiceManager.h"
#include "nsDebug.h"
#include "nsDebugImpl.h"
static nsIDebug* gDebugObject = nsnull;
static NS_METHOD FreeDebugObject(void)
{
NS_IF_RELEASE(gDebugObject);
return NS_OK;
}
#define ENSURE_DEBUGOBJECT \
(gDebugObject ? PR_TRUE : (PRBool)(SetupDebugObject() != nsnull))
static nsIDebug* SetupDebugObject()
{
NS_GetDebug(&gDebugObject);
if (gDebugObject)
NS_RegisterXPCOMExitRoutine(FreeDebugObject, 0);
return gDebugObject;
}
#ifdef XPCOM_GLUE
nsresult GlueStartupDebug()
{
NS_GetDebug(&gDebugObject);
if (!gDebugObject)
return NS_ERROR_FAILURE;
return NS_OK;
}
void GlueShutdownDebug()
{
NS_IF_RELEASE(gDebugObject);
}
#endif
void NS_FASTCALL
NSGlue_Abort(const char* aFile, PRIntn aLine)
{
if (!ENSURE_DEBUGOBJECT)
return;
gDebugObject->Abort(aFile, aLine);
}
void NS_FASTCALL
NSGlue_Break(const char* aFile, PRIntn aLine)
{
if (!ENSURE_DEBUGOBJECT)
return;
gDebugObject->Break(aFile, aLine);
}
void NS_FASTCALL
NSGlue_Warning(const char* aStr, const char* aFile, PRIntn aLine)
{
if (!ENSURE_DEBUGOBJECT)
return;
gDebugObject->Warning(aStr, aFile, aLine);
}
void NS_FASTCALL
NSGlue_Assertion(const char* aStr, const char* aExpr,
const char* aFile, PRIntn aLine)
{
if (!ENSURE_DEBUGOBJECT)
return;
gDebugObject->Assertion(aStr, aExpr, aFile, aLine);
}

View File

@ -46,45 +46,12 @@
#include "nsError.h"
#endif
#include "nsXPCOM.h"
#ifdef DEBUG
#define NS_DEBUG
#endif
/**
* Namespace for debugging methods. Note that your code must use the
* macros defined later in this file so that the debug code can be
* conditionally compiled out.
*/
PR_BEGIN_EXTERN_C
/**
* Log a warning message to the debug log.
*/
NS_COM_GLUE void NS_FASTCALL
NSGlue_Warning(const char *aMessage, const char *aFile, PRIntn aLine);
/**
* Abort the executing program. This works on all architectures.
*/
NS_COM_GLUE void NS_FASTCALL
NSGlue_Abort(const char *aFile, PRIntn aLine);
/**
* Break the executing program into the debugger.
*/
NS_COM_GLUE void NS_FASTCALL
NSGlue_Break(const char* aFile, PRIntn aLine);
/**
* Log an assertion message to the debug log
*/
NS_COM_GLUE void NS_FASTCALL
NSGlue_Assertion(const char* aStr, const char* aExpr,
const char* aFile, PRIntn aLine);
PR_END_EXTERN_C
#ifdef DEBUG
/**
@ -106,7 +73,7 @@ PR_END_EXTERN_C
#define NS_ABORT_IF_FALSE(_expr, _msg) \
PR_BEGIN_MACRO \
if (!(_expr)) { \
NSGlue_Assertion(_msg, #_expr, __FILE__, __LINE__); \
NS_DebugBreak(NS_DEBUG_ASSERTION, _msg, #_expr, __FILE__, __LINE__); \
} \
PR_END_MACRO
@ -121,7 +88,7 @@ PR_END_EXTERN_C
#define NS_WARN_IF_FALSE(_expr,_msg) \
PR_BEGIN_MACRO \
if (!(_expr)) { \
NSGlue_Assertion(_msg, #_expr, __FILE__, __LINE__); \
NS_DebugBreak(NS_DEBUG_ASSERTION, _msg, #_expr, __FILE__, __LINE__); \
} \
PR_END_MACRO
@ -132,7 +99,7 @@ PR_END_EXTERN_C
#define NS_PRECONDITION(expr, str) \
PR_BEGIN_MACRO \
if (!(expr)) { \
NSGlue_Assertion(str, #expr, __FILE__, __LINE__); \
NS_DebugBreak(NS_DEBUG_ASSERTION, str, #expr, __FILE__, __LINE__); \
} \
PR_END_MACRO
@ -143,7 +110,7 @@ PR_END_EXTERN_C
#define NS_ASSERTION(expr, str) \
PR_BEGIN_MACRO \
if (!(expr)) { \
NSGlue_Assertion(str, #expr, __FILE__, __LINE__); \
NS_DebugBreak(NS_DEBUG_ASSERTION, str, #expr, __FILE__, __LINE__); \
} \
PR_END_MACRO
@ -154,7 +121,7 @@ PR_END_EXTERN_C
#define NS_POSTCONDITION(expr, str) \
PR_BEGIN_MACRO \
if (!(expr)) { \
NSGlue_Assertion(str, #expr, __FILE__, __LINE__); \
NS_DebugBreak(NS_DEBUG_ASSERTION, str, #expr, __FILE__, __LINE__); \
} \
PR_END_MACRO
@ -163,38 +130,38 @@ PR_END_EXTERN_C
* an attempt was made to execute some unimplemented functionality.
*/
#define NS_NOTYETIMPLEMENTED(str) \
NSGlue_Assertion(str, "NotYetImplemented", __FILE__, __LINE__)
NS_DebugBreak(NS_DEBUG_ASSERTION, str, "NotYetImplemented", __FILE__, __LINE__)
/**
* This macros triggers a program failure if executed. It indicates that
* an attempt was made to execute some unimplemented functionality.
*/
#define NS_NOTREACHED(str) \
NSGlue_Assertion(str, "Not Reached", __FILE__, __LINE__)
NS_DebugBreak(NS_DEBUG_ASSERTION, str, "Not Reached", __FILE__, __LINE__)
/**
* Log an error message.
*/
#define NS_ERROR(str) \
NSGlue_Assertion(str, "Error", __FILE__, __LINE__)
NS_DebugBreak(NS_DEBUG_ASSERTION, str, "Error", __FILE__, __LINE__)
/**
* Log a warning message.
*/
#define NS_WARNING(str) \
NSGlue_Warning(str, __FILE__, __LINE__)
NS_DebugBreak(NS_DEBUG_WARNING, str, nsnull, __FILE__, __LINE__)
/**
* Trigger an abort
*/
#define NS_ABORT() \
NSGlue_Abort(__FILE__, __LINE__)
NS_DebugBreak(NS_DEBUG_ABORT, nsnull, nsnull, __FILE__, __LINE__)
/**
* Cause a break
*/
#define NS_BREAK() \
NSGlue_Break(__FILE__, __LINE__)
NS_DebugBreak(NS_DEBUG_BREAK, nsnull, nsnull, __FILE__, __LINE__)
#else /* NS_DEBUG */

View File

@ -1,125 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is XPCOM
*
* The Initial Developer of the Original Code is Doug Turner <dougt@meer.net>
*
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsXPCOM.h"
#include "nsXPCOMPrivate.h"
#include "nsCOMPtr.h"
#include "nsIServiceManager.h"
#include "nsTraceRefcnt.h"
#include "nsTraceRefcntImpl.h"
static nsITraceRefcnt* gTraceRefcntObject = nsnull;
static NS_METHOD FreeTraceRefcntObject(void)
{
NS_IF_RELEASE(gTraceRefcntObject);
return NS_OK;
}
#define ENSURE_TRACEOBJECT \
(gTraceRefcntObject || SetupTraceRefcntObject() != nsnull)
static nsITraceRefcnt* SetupTraceRefcntObject()
{
NS_GetTraceRefcnt(&gTraceRefcntObject);
if (gTraceRefcntObject)
NS_RegisterXPCOMExitRoutine(FreeTraceRefcntObject, 0);
return gTraceRefcntObject;
}
#ifdef XPCOM_GLUE
nsresult GlueStartupTraceRefcnt()
{
NS_GetTraceRefcnt(&gTraceRefcntObject);
if (!gTraceRefcntObject)
return NS_ERROR_FAILURE;
return NS_OK;
}
void GlueShutdownTraceRefcnt()
{
NS_IF_RELEASE(gTraceRefcntObject);
}
#endif
NS_COM_GLUE void
nsTraceRefcnt::LogAddRef(void * aPtr, nsrefcnt aNewRefcnt, const char *aTypeName, PRUint32 aInstanceSize)
{
if (!ENSURE_TRACEOBJECT)
return;
gTraceRefcntObject->LogAddRef(aPtr, aNewRefcnt, aTypeName, aInstanceSize);
}
NS_COM_GLUE void
nsTraceRefcnt::LogRelease(void * aPtr, nsrefcnt aNewRefcnt, const char *aTypeName)
{
if (!ENSURE_TRACEOBJECT)
return;
gTraceRefcntObject->LogRelease(aPtr, aNewRefcnt, aTypeName);
}
NS_COM_GLUE void
nsTraceRefcnt::LogCtor(void * aPtr, const char *aTypeName, PRUint32 aInstanceSize)
{
if (!ENSURE_TRACEOBJECT)
return;
gTraceRefcntObject->LogCtor(aPtr, aTypeName, aInstanceSize);
}
NS_COM_GLUE void
nsTraceRefcnt::LogDtor(void * aPtr, const char *aTypeName, PRUint32 aInstanceSize)
{
if (!ENSURE_TRACEOBJECT)
return;
gTraceRefcntObject->LogDtor(aPtr, aTypeName, aInstanceSize);
}
NS_COM_GLUE void
nsTraceRefcnt::LogAddCOMPtr(void * aPtr, nsISupports *aObject)
{
if (!ENSURE_TRACEOBJECT)
return;
gTraceRefcntObject->LogAddCOMPtr(aPtr, aObject);
}
NS_COM_GLUE void
nsTraceRefcnt::LogReleaseCOMPtr(void * aPtr, nsISupports *aObject)
{
if (!ENSURE_TRACEOBJECT)
return;
gTraceRefcntObject->LogReleaseCOMPtr(aPtr, aObject);
}

View File

@ -38,7 +38,7 @@
#ifndef nsTraceRefcnt_h___
#define nsTraceRefcnt_h___
#include "nscore.h"
#include "nsXPCOM.h"
class nsISupports;
@ -61,38 +61,33 @@ class nsISupports;
#ifdef NS_BUILD_REFCNT_LOGGING
#define NS_LOG_ADDREF(_p, _rc, _type, _size) \
nsTraceRefcnt::LogAddRef((_p), (_rc), (_type), (PRUint32) (_size))
NS_LogAddRef((_p), (_rc), (_type), (PRUint32) (_size))
#define NS_LOG_RELEASE(_p, _rc, _type) \
nsTraceRefcnt::LogRelease((_p), (_rc), (_type))
NS_LogRelease((_p), (_rc), (_type))
#define MOZ_DECL_CTOR_COUNTER(_type)
#define MOZ_COUNT_CTOR(_type) \
PR_BEGIN_MACRO \
nsTraceRefcnt::LogCtor((void*)this, #_type, sizeof(*this)); \
NS_LogCtor((void*)this, #_type, sizeof(*this)); \
PR_END_MACRO
#define MOZ_COUNT_DTOR(_type) \
PR_BEGIN_MACRO \
nsTraceRefcnt::LogDtor((void*)this, #_type, sizeof(*this)); \
NS_LogDtor((void*)this, #_type, sizeof(*this)); \
PR_END_MACRO
#ifdef HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR // from autoconf (XXX needs to be
// set for non-autoconf platforms)
// nsCOMPtr.h allows these macros to be defined by clients
// These logging functions require dynamic_cast<void *>, so we don't
// define these macros if we don't have dynamic_cast.
#define NSCAP_LOG_ASSIGNMENT(_c, _p) \
if (_p) \
nsTraceRefcnt::LogAddCOMPtr((_c),NS_STATIC_CAST(nsISupports*,_p))
NS_LogCOMPtrAddRef((_c),NS_STATIC_CAST(nsISupports*,_p))
#define NSCAP_LOG_RELEASE(_c, _p) \
if (_p) \
nsTraceRefcnt::LogReleaseCOMPtr((_c), NS_STATIC_CAST(nsISupports*,_p))
#endif /* HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR */
NS_LogCOMPtrRelease((_c), NS_STATIC_CAST(nsISupports*,_p))
#else /* !NS_BUILD_REFCNT_LOGGING */
@ -104,32 +99,35 @@ PR_END_MACRO
#endif /* NS_BUILD_REFCNT_LOGGING */
//----------------------------------------------------------------------
/**
* Note: The implementations for these methods are no-ops in a build
* where NS_BUILD_REFCNT_LOGGING is disabled.
*/
class nsTraceRefcnt {
public:
static NS_COM_GLUE void LogAddRef(void* aPtr,
nsrefcnt aNewRefCnt,
const char* aTypeName,
PRUint32 aInstanceSize);
inline static void LogAddRef(void* aPtr, nsrefcnt aNewRefCnt,
const char* aTypeName, PRUint32 aInstanceSize) {
NS_LogAddRef(aPtr, aNewRefCnt, aTypeName, aInstanceSize);
}
static NS_COM_GLUE void LogRelease(void* aPtr,
nsrefcnt aNewRefCnt,
const char* aTypeName);
inline static void LogRelease(void* aPtr, nsrefcnt aNewRefCnt,
const char* aTypeName) {
NS_LogRelease(aPtr, aNewRefCnt, aTypeName);
}
static NS_COM_GLUE void LogCtor(void* aPtr, const char* aTypeName,
PRUint32 aInstanceSize);
inline static void LogCtor(void* aPtr, const char* aTypeName,
PRUint32 aInstanceSize) {
NS_LogCtor(aPtr, aTypeName, aInstanceSize);
}
static NS_COM_GLUE void LogDtor(void* aPtr, const char* aTypeName,
PRUint32 aInstanceSize);
inline static void LogDtor(void* aPtr, const char* aTypeName,
PRUint32 aInstanceSize) {
NS_LogDtor(aPtr, aTypeName, aInstanceSize);
}
static NS_COM_GLUE void LogAddCOMPtr(void *aCOMPtr, nsISupports *aObject);
static NS_COM_GLUE void LogReleaseCOMPtr(void *aCOMPtr, nsISupports *aObject);
inline static void LogAddCOMPtr(void *aCOMPtr, nsISupports *aObject) {
NS_LogCOMPtrAddRef(aCOMPtr, aObject);
}
inline static void LogReleaseCOMPtr(void *aCOMPtr, nsISupports *aObject) {
NS_LogCOMPtrRelease(aCOMPtr, aObject);
}
};
#endif /* nsTraceRefcnt_h___ */

View File

@ -45,12 +45,10 @@ XPCOM_GLUE_SRC_LCPPSRCS = \
nsCOMArray.cpp \
nsCRTGlue.cpp \
nsComponentManagerUtils.cpp \
nsDebug.cpp \
nsID.cpp \
nsIInterfaceRequestorUtils.cpp \
nsINIParser.cpp \
nsMemory.cpp \
nsTraceRefcnt.cpp \
nsWeakReference.cpp \
nsGREGlue.cpp \
nsVersionComparator.cpp \

View File

@ -55,10 +55,6 @@
#define snprintf _snprintf
#endif
// functions provided by nsDebug.cpp
nsresult GlueStartupDebug();
void GlueShutdownDebug();
static XPCOMFunctions xpcomFunctions;
extern "C"
@ -83,13 +79,6 @@ nsresult XPCOMGlueStartup(const char* xpcomFile)
return rv;
}
rv = GlueStartupDebug();
if (NS_FAILED(rv)) {
memset(&xpcomFunctions, 0, sizeof(xpcomFunctions));
XPCOMGlueUnload();
return rv;
}
return NS_OK;
}
@ -132,8 +121,6 @@ XPCOMGlueLoadDependentLibs(const char *xpcomDir, DependentLibsCallback cb)
extern "C"
nsresult XPCOMGlueShutdown()
{
GlueShutdownDebug();
XPCOMGlueUnload();
memset(&xpcomFunctions, 0, sizeof(xpcomFunctions));
@ -452,6 +439,73 @@ NS_Free(void* ptr)
xpcomFunctions.freeFunc(ptr);
}
XPCOM_API(void)
NS_DebugBreak(PRUint32 aSeverity, const char *aStr, const char *aExpr,
const char *aFile, PRInt32 aLine)
{
if (xpcomFunctions.debugBreakFunc)
xpcomFunctions.debugBreakFunc(aSeverity, aStr, aExpr, aFile, aLine);
}
XPCOM_API(void)
NS_LogInit()
{
if (xpcomFunctions.logInitFunc)
xpcomFunctions.logInitFunc();
}
XPCOM_API(void)
NS_LogTerm()
{
if (xpcomFunctions.logTermFunc)
xpcomFunctions.logTermFunc();
}
XPCOM_API(void)
NS_LogAddRef(void *aPtr, nsrefcnt aNewRefCnt,
const char *aTypeName, PRUint32 aInstanceSize)
{
if (xpcomFunctions.logAddRefFunc)
xpcomFunctions.logAddRefFunc(aPtr, aNewRefCnt,
aTypeName, aInstanceSize);
}
XPCOM_API(void)
NS_LogRelease(void *aPtr, nsrefcnt aNewRefCnt, const char *aTypeName)
{
if (xpcomFunctions.logReleaseFunc)
xpcomFunctions.logReleaseFunc(aPtr, aNewRefCnt, aTypeName);
}
XPCOM_API(void)
NS_LogCtor(void *aPtr, const char *aTypeName, PRUint32 aInstanceSize)
{
if (xpcomFunctions.logCtorFunc)
xpcomFunctions.logCtorFunc(aPtr, aTypeName, aInstanceSize);
}
XPCOM_API(void)
NS_LogDtor(void *aPtr, const char *aTypeName, PRUint32 aInstanceSize)
{
if (xpcomFunctions.logDtorFunc)
xpcomFunctions.logDtorFunc(aPtr, aTypeName, aInstanceSize);
}
XPCOM_API(void)
NS_LogCOMPtrAddRef(void *aCOMPtr, nsISupports *aObject)
{
if (xpcomFunctions.logCOMPtrAddRefFunc)
xpcomFunctions.logCOMPtrAddRefFunc(aCOMPtr, aObject);
}
XPCOM_API(void)
NS_LogCOMPtrRelease(void *aCOMPtr, nsISupports *aObject)
{
if (xpcomFunctions.logCOMPtrReleaseFunc)
xpcomFunctions.logCOMPtrReleaseFunc(aCOMPtr, aObject);
}
// Default GRE startup/shutdown code
extern "C"

View File

@ -44,6 +44,7 @@ include $(DEPTH)/config/autoconf.mk
MODULE = xpcom
LIBRARY_NAME = xptcmd
MOZILLA_INTERNAL_API = 1
#
# The default is this buildable, but non-functioning code.

View File

@ -85,8 +85,19 @@ static const XPCOMFunctions kFrozenFunctions = {
&NS_CStringContainerInit2_P,
&NS_StringGetMutableData_P,
&NS_CStringGetMutableData_P,
&NS_InitXPCOM3_P
};
&NS_InitXPCOM3_P,
// these functions were added post 1.8
&NS_DebugBreak_P,
&NS_LogInit_P,
&NS_LogTerm_P,
&NS_LogAddRef_P,
&NS_LogRelease_P,
&NS_LogCtor_P,
&NS_LogDtor_P,
&NS_LogCOMPtrAddRef_P,
&NS_LogCOMPtrRelease_P
};
EXPORT_XPCOM_API(nsresult)
NS_GetFrozenFunctions(XPCOMFunctions *functions, const char* /* libraryPath */)
@ -221,6 +232,72 @@ NS_Free(void* ptr)
NS_Free_P(ptr);
}
#undef NS_DebugBreak
EXPORT_XPCOM_API(void)
NS_DebugBreak(PRUint32 aSeverity, const char *aStr, const char *aExpr,
const char *aFile, PRInt32 aLine)
{
NS_DebugBreak_P(aSeverity, aStr, aExpr, aFile, aLine);
}
#undef NS_LogInit
EXPORT_XPCOM_API(void)
NS_LogInit()
{
NS_LogInit_P();
}
#undef NS_LogTerm
EXPORT_XPCOM_API(void)
NS_LogTerm()
{
NS_LogTerm_P();
}
#undef NS_LogAddRef
EXPORT_XPCOM_API(void)
NS_LogAddRef(void* aPtr, nsrefcnt aNewRefCnt,
const char *aTypeName, PRUint32 aInstanceSize)
{
NS_LogAddRef_P(aPtr, aNewRefCnt, aTypeName, aInstanceSize);
}
#undef NS_LogRelease
EXPORT_XPCOM_API(void)
NS_LogRelease(void* aPtr, nsrefcnt aNewRefCnt, const char *aTypeName)
{
NS_LogRelease_P(aPtr, aNewRefCnt, aTypeName);
}
#undef NS_LogCtor
EXPORT_XPCOM_API(void)
NS_LogCtor(void *aPtr, const char *aTypeName, PRUint32 aInstanceSize)
{
NS_LogCtor_P(aPtr, aTypeName, aInstanceSize);
}
#undef NS_LogDtor
EXPORT_XPCOM_API(void)
NS_LogDtor(void *aPtr, const char *aTypeName, PRUint32 aInstanceSize)
{
NS_LogDtor_P(aPtr, aTypeName, aInstanceSize);
}
#undef NS_LogCOMPtrAddRef
EXPORT_XPCOM_API(void)
NS_LogCOMPtrAddRef(void *aCOMPtr, nsISupports* aObject)
{
NS_LogCOMPtrAddRef_P(aCOMPtr, aObject);
}
#undef NS_LogCOMPtrRelease
EXPORT_XPCOM_API(void)
NS_LogCOMPtrRelease(void *aCOMPtr, nsISupports* aObject)
{
NS_LogCOMPtrRelease_P(aCOMPtr, aObject);
}
/*
* Stubs for nsXPCOMPrivate.h
*/