Bug 1451366: Part 1 - Wait after launch from update and restart r=mhowell, jimm draft
authorAdam Gashlin <agashlin@mozilla.com>
Mon, 14 May 2018 14:49:24 -0700
changeset 795027 0629872de43ed312283c01d25fca9036233a61da
parent 793719 17db33b6a124422d43a9f518bea1bc62a698126b
child 795028 8afe52da4446577912c13d55110dcc06677d2d76
push id109841
push userbmo:agashlin@mozilla.com
push dateMon, 14 May 2018 21:53:27 +0000
reviewersmhowell, jimm
bugs1451366
milestone62.0a1
Bug 1451366: Part 1 - Wait after launch from update and restart r=mhowell, jimm MozReview-Commit-ID: GlzTYxx9yDh
toolkit/mozapps/update/updater/updater.cpp
toolkit/xre/nsAppRunner.cpp
xpcom/base/nsWindowsHelpers.h
--- 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