Bug 1451366: Part 1 - Wait after launch from update and restart r=mhowell, jimm
MozReview-Commit-ID: GlzTYxx9yDh
--- a/toolkit/mozapps/update/updater/updater.cpp
+++ b/toolkit/mozapps/update/updater/updater.cpp
@@ -2093,17 +2093,24 @@ LaunchCallbackApp(const NS_tchar *workin
#if defined(USE_EXECV)
execv(argv[0], argv);
#elif defined(XP_MACOSX)
LaunchChild(argc, (const char**)argv);
#elif defined(XP_WIN)
// Do not allow the callback to run when running an update through the
// service as session 0. The unelevated updater.exe will do the launching.
if (!usingService) {
- WinLaunchChild(argv[0], argc, argv, nullptr);
+ HANDLE hProcess;
+ if (WinLaunchChild(argv[0], argc, argv, nullptr, &hProcess)) {
+ // Keep the current process around until the callback process has created
+ // its message queue, to avoid the launched process's windows being forced
+ // into the background.
+ WaitForInputIdle(hProcess, kWaitForInputIdleTimeoutMS);
+ CloseHandle(hProcess);
+ }
}
#else
# warning "Need implementaton of LaunchCallbackApp"
#endif
}
static bool
WriteStatusFile(const char* aStatus)
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -1786,18 +1786,24 @@ static nsresult LaunchChild(nsINativeApp
return rv;
#if defined(XP_WIN)
nsAutoString exePath;
rv = lf->GetPath(exePath);
if (NS_FAILED(rv))
return rv;
- if (!WinLaunchChild(exePath.get(), gRestartArgc, gRestartArgv))
+ HANDLE hProcess;
+ if (!WinLaunchChild(exePath.get(), gRestartArgc, gRestartArgv, nullptr, &hProcess))
return NS_ERROR_FAILURE;
+ // Keep the current process around until the restarted process has created
+ // its message queue, to avoid the launched process's windows being forced
+ // into the background.
+ ::WaitForInputIdle(hProcess, kWaitForInputIdleTimeoutMS);
+ ::CloseHandle(hProcess);
#else
nsAutoCString exePath;
rv = lf->GetNativePath(exePath);
if (NS_FAILED(rv))
return rv;
#if defined(XP_UNIX)
--- a/xpcom/base/nsWindowsHelpers.h
+++ b/xpcom/base/nsWindowsHelpers.h
@@ -363,9 +363,14 @@ LoadLibrarySystem32(LPCWSTR aModule)
if (!ConstructSystem32Path(aModule, systemPath, MAX_PATH + 1)) {
return NULL;
}
return LoadLibraryW(systemPath);
}
}
+// How long to wait for a created process to become available for input,
+// to prevent that process's windows being forced to the background.
+// This is used across update, restart, and the launcher.
+const DWORD kWaitForInputIdleTimeoutMS = 10*1000;
+
#endif