Bug 921063 - Lock and (potentially) wait for remote service startup. r=glandium

MozReview-Commit-ID: 5MRX9TtxTLo

--HG--
extra : rebase_source : d836573b16aa52199750f50208710294e921bfa1
This commit is contained in:
Luca Niccoli 2016-09-20 11:14:12 +02:00
Родитель 40284ca39a
Коммит dda95d5cd3
1 изменённых файлов: 70 добавлений и 13 удалений

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

@ -168,6 +168,11 @@
#ifdef MOZ_ENABLE_XREMOTE #ifdef MOZ_ENABLE_XREMOTE
#include "XRemoteClient.h" #include "XRemoteClient.h"
#include "nsIRemoteService.h" #include "nsIRemoteService.h"
#include "nsProfileLock.h"
#include "SpecialSystemDirectory.h"
#include <sched.h>
// Time to wait for the remoting service to start
#define MOZ_XREMOTE_START_TIMEOUT_SEC 5
#endif #endif
#if defined(DEBUG) && defined(XP_WIN32) #if defined(DEBUG) && defined(XP_WIN32)
@ -1679,17 +1684,13 @@ DumpVersion()
#ifdef MOZ_ENABLE_XREMOTE #ifdef MOZ_ENABLE_XREMOTE
static RemoteResult static RemoteResult
RemoteCommandLine(const char* aDesktopStartupID) ParseRemoteCommandLine(nsCString& program,
const char** profile,
const char** username)
{ {
nsresult rv;
ArgResult ar; ArgResult ar;
const char *profile = 0; ar = CheckArg("p", false, profile, false);
nsAutoCString program(gAppData->remotingName);
ToLowerCase(program);
const char *username = getenv("LOGNAME");
ar = CheckArg("p", false, &profile, false);
if (ar == ARG_BAD) { if (ar == ARG_BAD) {
// Leave it to the normal command line handling to handle this situation. // Leave it to the normal command line handling to handle this situation.
return REMOTE_NOT_FOUND; return REMOTE_NOT_FOUND;
@ -1704,14 +1705,23 @@ RemoteCommandLine(const char* aDesktopStartupID)
program.Assign(temp); program.Assign(temp);
} }
ar = CheckArg("u", true, &username); ar = CheckArg("u", true, username);
if (ar == ARG_BAD) { if (ar == ARG_BAD) {
PR_fprintf(PR_STDERR, "Error: argument -u requires a username\n"); PR_fprintf(PR_STDERR, "Error: argument -u requires a username\n");
return REMOTE_ARG_BAD; return REMOTE_ARG_BAD;
} }
return REMOTE_FOUND;
}
static RemoteResult
StartRemoteClient(const char* aDesktopStartupID,
nsCString& program,
const char* profile,
const char* username)
{
XRemoteClient client; XRemoteClient client;
rv = client.Init(); nsresult rv = client.Init();
if (NS_FAILED(rv)) if (NS_FAILED(rv))
return REMOTE_NOT_FOUND; return REMOTE_NOT_FOUND;
@ -3018,6 +3028,8 @@ public:
nsCOMPtr<nsIProfileLock> mProfileLock; nsCOMPtr<nsIProfileLock> mProfileLock;
#ifdef MOZ_ENABLE_XREMOTE #ifdef MOZ_ENABLE_XREMOTE
nsCOMPtr<nsIRemoteService> mRemoteService; nsCOMPtr<nsIRemoteService> mRemoteService;
nsProfileLock mRemoteLock;
nsCOMPtr<nsIFile> mRemoteLockDir;
#endif #endif
UniquePtr<ScopedXPCOMStartup> mScopedXPCOM; UniquePtr<ScopedXPCOMStartup> mScopedXPCOM;
@ -3755,17 +3767,58 @@ XREMain::XRE_mainStartup(bool* aExitFlag)
} }
if (!newInstance) { if (!newInstance) {
nsAutoCString program(gAppData->remotingName);
ToLowerCase(program);
const char* username = getenv("LOGNAME");
const char* profile = nullptr;
RemoteResult rr = ParseRemoteCommandLine(program, &profile, &username);
if (rr == REMOTE_ARG_BAD) {
return 1;
}
nsCOMPtr<nsIFile> mutexDir;
rv = GetSpecialSystemDirectory(OS_TemporaryDirectory, getter_AddRefs(mutexDir));
if (NS_SUCCEEDED(rv)) {
nsAutoCString mutexPath =
program + NS_LITERAL_CSTRING("_") + nsDependentCString(username);
if (profile) {
mutexPath.Append(NS_LITERAL_CSTRING("_") + nsDependentCString(profile));
}
mutexDir->AppendNative(mutexPath);
rv = mutexDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
if (NS_SUCCEEDED(rv) || rv == NS_ERROR_FILE_ALREADY_EXISTS) {
mRemoteLockDir = mutexDir;
}
}
if (mRemoteLockDir) {
const TimeStamp epoch = mozilla::TimeStamp::Now();
do {
rv = mRemoteLock.Lock(mRemoteLockDir, nullptr);
if (NS_SUCCEEDED(rv))
break;
sched_yield();
} while ((TimeStamp::Now() - epoch)
< TimeDuration::FromSeconds(MOZ_XREMOTE_START_TIMEOUT_SEC));
if (NS_FAILED(rv)) {
NS_WARNING("Cannot lock XRemote start mutex");
}
}
// Try to remote the entire command line. If this fails, start up normally. // Try to remote the entire command line. If this fails, start up normally.
const char* desktopStartupIDPtr = const char* desktopStartupIDPtr =
mDesktopStartupID.IsEmpty() ? nullptr : mDesktopStartupID.get(); mDesktopStartupID.IsEmpty() ? nullptr : mDesktopStartupID.get();
RemoteResult rr = RemoteCommandLine(desktopStartupIDPtr); rr = StartRemoteClient(desktopStartupIDPtr, program, profile, username);
if (rr == REMOTE_FOUND) { if (rr == REMOTE_FOUND) {
*aExitFlag = true; *aExitFlag = true;
return 0; return 0;
} } else if (rr == REMOTE_ARG_BAD) {
else if (rr == REMOTE_ARG_BAD)
return 1; return 1;
}
} }
#endif #endif
#if defined(MOZ_WIDGET_GTK) #if defined(MOZ_WIDGET_GTK)
@ -4331,6 +4384,10 @@ XREMain::XRE_mainRun()
mRemoteService = do_GetService("@mozilla.org/toolkit/remote-service;1"); mRemoteService = do_GetService("@mozilla.org/toolkit/remote-service;1");
if (mRemoteService) if (mRemoteService)
mRemoteService->Startup(mAppData->remotingName, mProfileName.get()); mRemoteService->Startup(mAppData->remotingName, mProfileName.get());
if (mRemoteLockDir) {
mRemoteLock.Unlock();
mRemoteLockDir->Remove(false);
}
#endif /* MOZ_ENABLE_XREMOTE */ #endif /* MOZ_ENABLE_XREMOTE */
mNativeApp->Enable(); mNativeApp->Enable();