forked from mirrors/gecko-dev
Firefox 84.0.1 crashes under Gentoo Linux if it is started in Wayland mode and if it was compiled WITH Wayland support and WITHOUT dbus support. I traced down the problem to line 172 of toolkit/components/remote/nsRemoteService.cpp: nsresult rv = mRemoteServer->Startup(mProgram.get(), mProfile.get()); mRemoteServer is NULL and Firefox crashes. This patch adds a NULL pointer check before that line. See: - Mozilla's Bugzilla, bug 1684365 - https://bugs.gentoo.org/762035 - https://forums.gentoo.org/viewtopic-t-1126235.html Differential Revision: https://phabricator.services.mozilla.com/D101536
206 lines
5.4 KiB
C++
206 lines
5.4 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim:expandtab:shiftwidth=2:tabstop=8:
|
|
*/
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#ifdef XP_UNIX
|
|
# include <sys/types.h>
|
|
# include <pwd.h>
|
|
#endif
|
|
|
|
#ifdef MOZ_WIDGET_GTK
|
|
# include "nsGTKRemoteServer.h"
|
|
# include "nsXRemoteClient.h"
|
|
# ifdef MOZ_ENABLE_DBUS
|
|
# include "nsDBusRemoteServer.h"
|
|
# include "nsDBusRemoteClient.h"
|
|
# endif
|
|
#elif defined(XP_WIN)
|
|
# include "nsWinRemoteServer.h"
|
|
# include "nsWinRemoteClient.h"
|
|
#elif defined(XP_DARWIN)
|
|
# include "nsMacRemoteServer.h"
|
|
# include "nsMacRemoteClient.h"
|
|
#endif
|
|
#include "nsRemoteService.h"
|
|
|
|
#include "nsIObserverService.h"
|
|
#include "nsString.h"
|
|
#include "nsServiceManagerUtils.h"
|
|
#include "mozilla/ModuleUtils.h"
|
|
#include "SpecialSystemDirectory.h"
|
|
#include "mozilla/CmdLineAndEnvUtils.h"
|
|
#include "mozilla/TimeStamp.h"
|
|
#include "mozilla/UniquePtr.h"
|
|
|
|
// Time to wait for the remoting service to start
|
|
#define START_TIMEOUT_SEC 5
|
|
#define START_SLEEP_MSEC 100
|
|
|
|
// When MOZ_DBUS_REMOTE is set both X11 and Wayland backends
|
|
// use only DBus remote.
|
|
#define DBUS_REMOTE_ENV "MOZ_DBUS_REMOTE"
|
|
|
|
using namespace mozilla;
|
|
|
|
extern int gArgc;
|
|
extern char** gArgv;
|
|
|
|
using namespace mozilla;
|
|
|
|
NS_IMPL_ISUPPORTS(nsRemoteService, nsIObserver)
|
|
|
|
nsRemoteService::nsRemoteService(const char* aProgram) : mProgram(aProgram) {
|
|
ToLowerCase(mProgram);
|
|
}
|
|
|
|
void nsRemoteService::SetProfile(nsACString& aProfile) { mProfile = aProfile; }
|
|
|
|
void nsRemoteService::LockStartup() {
|
|
nsCOMPtr<nsIFile> mutexDir;
|
|
nsresult rv = GetSpecialSystemDirectory(OS_TemporaryDirectory,
|
|
getter_AddRefs(mutexDir));
|
|
if (NS_SUCCEEDED(rv)) {
|
|
mutexDir->AppendNative(mProgram);
|
|
|
|
rv = mutexDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
|
|
if (NS_SUCCEEDED(rv) || rv == NS_ERROR_FILE_ALREADY_EXISTS) {
|
|
mRemoteLockDir = mutexDir;
|
|
}
|
|
}
|
|
|
|
if (mRemoteLockDir) {
|
|
const mozilla::TimeStamp epoch = mozilla::TimeStamp::Now();
|
|
do {
|
|
rv = mRemoteLock.Lock(mRemoteLockDir, nullptr);
|
|
if (NS_SUCCEEDED(rv)) break;
|
|
PR_Sleep(START_SLEEP_MSEC);
|
|
} while ((mozilla::TimeStamp::Now() - epoch) <
|
|
mozilla::TimeDuration::FromSeconds(START_TIMEOUT_SEC));
|
|
if (NS_FAILED(rv)) {
|
|
NS_WARNING("Cannot lock remote start mutex");
|
|
}
|
|
}
|
|
}
|
|
|
|
void nsRemoteService::UnlockStartup() {
|
|
if (mRemoteLockDir) {
|
|
mRemoteLock.Unlock();
|
|
mRemoteLock.Cleanup();
|
|
|
|
mRemoteLockDir->Remove(false);
|
|
mRemoteLockDir = nullptr;
|
|
}
|
|
}
|
|
|
|
RemoteResult nsRemoteService::StartClient(const char* aDesktopStartupID) {
|
|
if (mProfile.IsEmpty()) {
|
|
return REMOTE_NOT_FOUND;
|
|
}
|
|
|
|
UniquePtr<nsRemoteClient> client;
|
|
|
|
#ifdef MOZ_WIDGET_GTK
|
|
bool useX11Remote = GDK_IS_X11_DISPLAY(gdk_display_get_default());
|
|
|
|
# if defined(MOZ_ENABLE_DBUS)
|
|
if (!useX11Remote || getenv(DBUS_REMOTE_ENV)) {
|
|
client = MakeUnique<nsDBusRemoteClient>();
|
|
}
|
|
# endif
|
|
if (!client && useX11Remote) {
|
|
client = MakeUnique<nsXRemoteClient>();
|
|
}
|
|
#elif defined(XP_WIN)
|
|
client = MakeUnique<nsWinRemoteClient>();
|
|
#elif defined(XP_DARWIN)
|
|
client = MakeUnique<nsMacRemoteClient>();
|
|
#else
|
|
return REMOTE_NOT_FOUND;
|
|
#endif
|
|
|
|
nsresult rv = client ? client->Init() : NS_ERROR_FAILURE;
|
|
if (NS_FAILED(rv)) return REMOTE_NOT_FOUND;
|
|
|
|
nsCString response;
|
|
bool success = false;
|
|
rv = client->SendCommandLine(mProgram.get(), mProfile.get(), gArgc, gArgv,
|
|
aDesktopStartupID, getter_Copies(response),
|
|
&success);
|
|
// did the command fail?
|
|
if (!success) return REMOTE_NOT_FOUND;
|
|
|
|
// The "command not parseable" error is returned when the
|
|
// nsICommandLineHandler throws a NS_ERROR_ABORT.
|
|
if (response.EqualsLiteral("500 command not parseable"))
|
|
return REMOTE_ARG_BAD;
|
|
|
|
if (NS_FAILED(rv)) return REMOTE_NOT_FOUND;
|
|
|
|
return REMOTE_FOUND;
|
|
}
|
|
|
|
void nsRemoteService::StartupServer() {
|
|
if (mRemoteServer) {
|
|
return;
|
|
}
|
|
|
|
if (mProfile.IsEmpty()) {
|
|
return;
|
|
}
|
|
|
|
#ifdef MOZ_WIDGET_GTK
|
|
bool useX11Remote = GDK_IS_X11_DISPLAY(gdk_display_get_default());
|
|
|
|
# if defined(MOZ_ENABLE_DBUS)
|
|
if (!useX11Remote || getenv(DBUS_REMOTE_ENV)) {
|
|
mRemoteServer = MakeUnique<nsDBusRemoteServer>();
|
|
}
|
|
# endif
|
|
if (!mRemoteServer && useX11Remote) {
|
|
mRemoteServer = MakeUnique<nsGTKRemoteServer>();
|
|
}
|
|
#elif defined(XP_WIN)
|
|
mRemoteServer = MakeUnique<nsWinRemoteServer>();
|
|
#elif defined(XP_DARWIN)
|
|
mRemoteServer = MakeUnique<nsMacRemoteServer>();
|
|
#else
|
|
return;
|
|
#endif
|
|
|
|
if (!mRemoteServer) {
|
|
return;
|
|
}
|
|
|
|
nsresult rv = mRemoteServer->Startup(mProgram.get(), mProfile.get());
|
|
|
|
if (NS_FAILED(rv)) {
|
|
mRemoteServer = nullptr;
|
|
return;
|
|
}
|
|
|
|
nsCOMPtr<nsIObserverService> obs(
|
|
do_GetService("@mozilla.org/observer-service;1"));
|
|
if (obs) {
|
|
obs->AddObserver(this, "xpcom-shutdown", false);
|
|
obs->AddObserver(this, "quit-application", false);
|
|
}
|
|
}
|
|
|
|
void nsRemoteService::ShutdownServer() { mRemoteServer = nullptr; }
|
|
|
|
nsRemoteService::~nsRemoteService() {
|
|
UnlockStartup();
|
|
ShutdownServer();
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsRemoteService::Observe(nsISupports* aSubject, const char* aTopic,
|
|
const char16_t* aData) {
|
|
// This can be xpcom-shutdown or quit-application, but it's the same either
|
|
// way.
|
|
ShutdownServer();
|
|
return NS_OK;
|
|
}
|