Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/winsup
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2011-12-12 14:16:53 +0400
committerCorinna Vinschen <corinna@vinschen.de>2011-12-12 14:16:53 +0400
commitcdce73f183d46a202c632486d5bd82d515cb05be (patch)
tree427c3983392f65bc48fb3ccb47f2c80fedcfa27e /winsup
parentb11797ad173cad16f65d469860ce056e7bff2b52 (diff)
* dcrt0.cc (wow64_respawn): New static variable.
(wow64_started_from_native64): New function to check if a WOW64 process got started from a native 64 bit process. (respawn_wow64_process): New function to respawn process. (dll_crt0_0): When started from a native parent, check if parent is a 64 bit process. If so, return early. (_dll_crt0): Respawn WOW64 process here if required. * init.cc (respawn_wow64_process): Remove. (dll_entry): Rename wow64_test_stack_marker to test_stack_marker. Drop WOW64 test here.
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog14
-rw-r--r--winsup/cygwin/dcrt0.cc86
-rw-r--r--winsup/cygwin/init.cc60
3 files changed, 101 insertions, 59 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index a2789f494..ef7fa4d04 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,17 @@
+2011-12-12 Corinna Vinschen <vinschen@redhat.com>
+ Christopher Faylor <me.cygwin2011@cgf.cx>
+
+ * dcrt0.cc (wow64_respawn): New static variable.
+ (wow64_started_from_native64): New function to check if a WOW64
+ process got started from a native 64 bit process.
+ (respawn_wow64_process): New function to respawn process.
+ (dll_crt0_0): When started from a native parent, check if parent
+ is a 64 bit process. If so, return early.
+ (_dll_crt0): Respawn WOW64 process here if required.
+ * init.cc (respawn_wow64_process): Remove.
+ (dll_entry): Rename wow64_test_stack_marker to test_stack_marker.
+ Drop WOW64 test here.
+
2011-12-11 Christopher Faylor <me.cygwin2011@cgf.cx>
* pipe.cc (fhandler_pipe::create): Use debug_printf to print debugging
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
index 6c13eff95..5364e4dd8 100644
--- a/winsup/cygwin/dcrt0.cc
+++ b/winsup/cygwin/dcrt0.cc
@@ -646,6 +646,75 @@ init_windows_system_directory ()
windows_system_directory[windows_system_directory_length] = L'\0';
}
+static bool NO_COPY wow64_respawn = false;
+
+inline static bool
+wow64_started_from_native64 ()
+{
+ /* On Windows XP 64 and 2003 64 there's a problem with processes running
+ under WOW64. The first process started from a 64 bit process has an
+ unusual stack address for the main thread. That is, an address which
+ is in the usual space occupied by the process image, but below the auto
+ load address of DLLs. If we encounter this situation, check if we
+ really have been started from a 64 bit process here. If so, we exit
+ early from dll_crt0_0 and respawn first thing in dll_crt0_1. This
+ ping-pong game is necessary to workaround a problem observed on
+ Windows 2003 R2 64. Starting with Cygwin 1.7.10 we don't link against
+ advapi32.dll anymore. However, *any* process linked against advapi32,
+ directly or indirectly, now fails to respawn if respawn_wow_64_process
+ is called during DLL_PROCESS_ATTACH initialization. In that case
+ CreateProcessW returns with ERROR_ACCESS_DENIED for some reason.
+ Calling CreateProcessW later, inside dll_crt0_1 and so outside of
+ dll initialization works as before, though. */
+ NTSTATUS ret;
+ PROCESS_BASIC_INFORMATION pbi;
+ HANDLE parent;
+
+ ULONG wow64 = TRUE; /* Opt on the safe side. */
+
+ /* Unfortunately there's no simpler way to retrieve the
+ parent process in NT, as far as I know. Hints welcome. */
+ ret = NtQueryInformationProcess (NtCurrentProcess (),
+ ProcessBasicInformation,
+ &pbi, sizeof pbi, NULL);
+ if (NT_SUCCESS (ret)
+ && (parent = OpenProcess (PROCESS_QUERY_INFORMATION,
+ FALSE,
+ pbi.InheritedFromUniqueProcessId)))
+ {
+ NtQueryInformationProcess (parent, ProcessWow64Information,
+ &wow64, sizeof wow64, NULL);
+ CloseHandle (parent);
+ }
+ return !wow64;
+}
+
+inline static void
+respawn_wow64_process ()
+{
+ /* The parent is a real 64 bit process. Respawn. */
+ WCHAR path[PATH_MAX];
+ PROCESS_INFORMATION pi;
+ STARTUPINFOW si;
+ DWORD ret = 0;
+
+ GetModuleFileNameW (NULL, path, PATH_MAX);
+ GetStartupInfoW (&si);
+ if (!CreateProcessW (path, GetCommandLineW (), NULL, NULL, TRUE,
+ CREATE_DEFAULT_ERROR_MODE
+ | GetPriorityClass (GetCurrentProcess ()),
+ NULL, NULL, &si, &pi))
+ api_fatal ("Failed to create process <%W> <%W>, %E",
+ path, GetCommandLineW ());
+ CloseHandle (pi.hThread);
+ if (WaitForSingleObject (pi.hProcess, INFINITE) == WAIT_FAILED)
+ api_fatal ("Waiting for process %d failed, %E", pi.dwProcessId);
+ GetExitCodeProcess (pi.hProcess, &ret);
+ CloseHandle (pi.hProcess);
+ TerminateProcess (GetCurrentProcess (), ret);
+ ExitProcess (ret);
+}
+
void
dll_crt0_0 ()
{
@@ -677,7 +746,18 @@ dll_crt0_0 ()
cygthread::init ();
if (!child_proc_info)
- memory_init (true);
+ {
+ memory_init (true);
+ /* WOW64 bit process with stack at unusual address? Check if we
+ have been started from 64 bit process ans set wow64_respawn.
+ Full description in wow64_started_from_native64 above. */
+ BOOL wow64_test_stack_marker;
+ if (wincap.is_wow64 ()
+ && &wow64_test_stack_marker >= (PBOOL) 0x400000
+ && &wow64_test_stack_marker <= (PBOOL) 0x10000000
+ && (wow64_respawn = wow64_started_from_native64 ()))
+ return;
+ }
else
{
cygwin_user_h = child_proc_info->user_h;
@@ -912,6 +992,10 @@ __cygwin_exit_return: \n\
extern "C" void __stdcall
_dll_crt0 ()
{
+ /* Respawn WOW64 process started from native 64 bit process. See comment
+ in wow64_started_from_native64 above for a full description. */
+ if (wow64_respawn)
+ respawn_wow64_process ();
#ifdef __i386__
_feinitialise ();
#endif
diff --git a/winsup/cygwin/init.cc b/winsup/cygwin/init.cc
index 107d037f9..5b0416125 100644
--- a/winsup/cygwin/init.cc
+++ b/winsup/cygwin/init.cc
@@ -64,58 +64,12 @@ munge_threadfunc ()
}
}
-inline static void
-respawn_wow64_process ()
-{
- NTSTATUS ret;
- PROCESS_BASIC_INFORMATION pbi;
- HANDLE parent;
-
- ULONG wow64 = TRUE; /* Opt on the safe side. */
-
- /* Unfortunately there's no simpler way to retrieve the
- parent process in NT, as far as I know. Hints welcome. */
- ret = NtQueryInformationProcess (NtCurrentProcess (),
- ProcessBasicInformation,
- &pbi, sizeof pbi, NULL);
- if (NT_SUCCESS (ret)
- && (parent = OpenProcess (PROCESS_QUERY_INFORMATION,
- FALSE,
- pbi.InheritedFromUniqueProcessId)))
- {
- NtQueryInformationProcess (parent, ProcessWow64Information,
- &wow64, sizeof wow64, NULL);
- CloseHandle (parent);
- }
-
- /* The parent is a real 64 bit process? Respawn! */
- if (!wow64)
- {
- PROCESS_INFORMATION pi;
- STARTUPINFOW si;
- DWORD ret = 0;
-
- GetStartupInfoW (&si);
- if (!CreateProcessW (NULL, GetCommandLineW (), NULL, NULL, TRUE,
- CREATE_DEFAULT_ERROR_MODE
- | GetPriorityClass (GetCurrentProcess ()),
- NULL, NULL, &si, &pi))
- api_fatal ("Failed to create process <%s>, %E", GetCommandLineA ());
- CloseHandle (pi.hThread);
- if (WaitForSingleObject (pi.hProcess, INFINITE) == WAIT_FAILED)
- api_fatal ("Waiting for process %d failed, %E", pi.dwProcessId);
- GetExitCodeProcess (pi.hProcess, &ret);
- CloseHandle (pi.hProcess);
- ExitProcess (ret);
- }
-}
-
void dll_crt0_0 ();
extern "C" BOOL WINAPI
dll_entry (HANDLE h, DWORD reason, void *static_load)
{
- BOOL wow64_test_stack_marker;
+ BOOL test_stack_marker;
switch (reason)
{
@@ -126,16 +80,6 @@ dll_entry (HANDLE h, DWORD reason, void *static_load)
cygwin_hmodule = (HMODULE) h;
dynamically_loaded = (static_load == NULL);
- /* Is the stack at an unusual address? That is, an address which
- is in the usual space occupied by the process image, but below
- the auto load address of DLLs?
- Check if we're running in WOW64 on a 64 bit machine *and* are
- spawned by a genuine 64 bit process. If so, respawn. */
- if (wincap.is_wow64 ()
- && &wow64_test_stack_marker >= (PBOOL) 0x400000
- && &wow64_test_stack_marker <= (PBOOL) 0x10000000)
- respawn_wow64_process ();
-
dll_crt0_0 ();
_my_oldfunc = TlsAlloc ();
dll_finished_loading = true;
@@ -150,7 +94,7 @@ dll_entry (HANDLE h, DWORD reason, void *static_load)
break;
case DLL_THREAD_DETACH:
if (dll_finished_loading
- && (PVOID) &_my_tls > (PVOID) &wow64_test_stack_marker
+ && (PVOID) &_my_tls > (PVOID) &test_stack_marker
&& _my_tls.isinitialized ())
_my_tls.remove (0);
/* Windows 2000 has a bug in NtTerminateThread. Instead of releasing