Add ChangeLog entry for previous change and revert erroneously checked in
changes to dcrt0.cc and init.cc
This commit is contained in:
		| @@ -1,3 +1,8 @@ | |||||||
|  | 2011-12-10  Christopher Faylor  <me.cygwin2011@cgf.cx> | ||||||
|  |  | ||||||
|  | 	* sigproc.h (cygwait): Tweak test for cancellable event to make it a | ||||||
|  | 	little more clear. | ||||||
|  |  | ||||||
| 2011-12-09  Christopher Faylor  <me.cygwin2011@cgf.cx> | 2011-12-09  Christopher Faylor  <me.cygwin2011@cgf.cx> | ||||||
|  |  | ||||||
| 	* exceptions.cc (ctrl_c_handler): YA in a series or reversions.  Put | 	* exceptions.cc (ctrl_c_handler): YA in a series or reversions.  Put | ||||||
|   | |||||||
| @@ -646,89 +646,10 @@ init_windows_system_directory () | |||||||
|   windows_system_directory[windows_system_directory_length] = L'\0'; |   windows_system_directory[windows_system_directory_length] = L'\0'; | ||||||
| } | } | ||||||
|  |  | ||||||
| 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 | void | ||||||
| dll_crt0_0 () | dll_crt0_0 () | ||||||
| { | { | ||||||
|   child_proc_info = get_cygwin_startup_info (); |   child_proc_info = get_cygwin_startup_info (); | ||||||
|   BOOL wow64_test_stack_marker; |  | ||||||
|   if (!child_proc_info |  | ||||||
|       && wincap.is_wow64 () |  | ||||||
|       /* 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. */ |  | ||||||
|       && &wow64_test_stack_marker >= (PBOOL) 0x400000 |  | ||||||
|       && &wow64_test_stack_marker <= (PBOOL) 0x10000000 |  | ||||||
|       && (wow64_respawn = wow64_started_from_native64 ())) |  | ||||||
|     return; |  | ||||||
|   init_windows_system_directory (); |   init_windows_system_directory (); | ||||||
|   init_global_security (); |   init_global_security (); | ||||||
|   initial_env (); |   initial_env (); | ||||||
| @@ -991,10 +912,6 @@ __cygwin_exit_return:			\n\ | |||||||
| extern "C" void __stdcall | extern "C" void __stdcall | ||||||
| _dll_crt0 () | _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__ | #ifdef __i386__ | ||||||
|   _feinitialise (); |   _feinitialise (); | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -64,12 +64,58 @@ 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 (); | void dll_crt0_0 (); | ||||||
|  |  | ||||||
| extern "C" BOOL WINAPI | extern "C" BOOL WINAPI | ||||||
| dll_entry (HANDLE h, DWORD reason, void *static_load) | dll_entry (HANDLE h, DWORD reason, void *static_load) | ||||||
| { | { | ||||||
|   extern bool wow64_respawn; |   BOOL wow64_test_stack_marker; | ||||||
|  |  | ||||||
|   switch (reason) |   switch (reason) | ||||||
|     { |     { | ||||||
| @@ -80,6 +126,16 @@ dll_entry (HANDLE h, DWORD reason, void *static_load) | |||||||
|       cygwin_hmodule = (HMODULE) h; |       cygwin_hmodule = (HMODULE) h; | ||||||
|       dynamically_loaded = (static_load == NULL); |       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 (); |       dll_crt0_0 (); | ||||||
|       _my_oldfunc = TlsAlloc (); |       _my_oldfunc = TlsAlloc (); | ||||||
|       dll_finished_loading = true; |       dll_finished_loading = true; | ||||||
| @@ -94,7 +150,7 @@ dll_entry (HANDLE h, DWORD reason, void *static_load) | |||||||
|       break; |       break; | ||||||
|     case DLL_THREAD_DETACH: |     case DLL_THREAD_DETACH: | ||||||
|       if (dll_finished_loading |       if (dll_finished_loading | ||||||
| 	  && !wow64_respawn | 	  && (PVOID) &_my_tls > (PVOID) &wow64_test_stack_marker | ||||||
| 	  && _my_tls.isinitialized ()) | 	  && _my_tls.isinitialized ()) | ||||||
| 	_my_tls.remove (0); | 	_my_tls.remove (0); | ||||||
|       /* Windows 2000 has a bug in NtTerminateThread.  Instead of releasing |       /* Windows 2000 has a bug in NtTerminateThread.  Instead of releasing | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user