diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index bfa587740..baf5a336b 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,21 @@ +2014-10-17 Corinna Vinschen + + * cygheap.cc (cygheap_fixup_in_child): Call set_dll_dir. + (init_cygheap::init_installation_root): Just memmove contents of + installation_root instead of calling GetModuleFileNameW again. + Copy installation_root to installation_dir before stripping of + "bin" dir. Don't call SetDllDirectory here. Explain what we do. + (setup_cygheap): New function taking over initial cygheap setup + from memory_init. Additionally call set_dll_dir. + * cygheap.h (struct init_cygheap): Add installation_dir member. + (init_cygheap::set_dll_dir): Define. + (setup_cygheap): Declare. + * dcrt0.cc: Throughout drop parameter from memory_init call. + (dll_crt0_0): Call setup_cygheap prior to memory_init. + * dlfcn.cc (dlopen): Change comment to point to the right function. + * shared.cc (memory_init): Drop parameter. Drop cygheap setup. + * shared_info.h (memory_init): Change declaration accordingly. + 2014-10-17 Corinna Vinschen * cygtls.h (__try): Define __l_endtry as block-local label in 32 bit diff --git a/winsup/cygwin/cygheap.cc b/winsup/cygwin/cygheap.cc index 7e261ed48..8e25a07ea 100644 --- a/winsup/cygwin/cygheap.cc +++ b/winsup/cygwin/cygheap.cc @@ -83,6 +83,7 @@ cygheap_fixup_in_child (bool execed) _csbrk ((char *) child_proc_info->cygheap_max - (char *) cygheap); child_copy (child_proc_info->parent, false, "cygheap", cygheap, cygheap_max, NULL); cygheap_init (); + cygheap->set_dll_dir (); debug_fixup_after_fork_exec (); if (execed) { @@ -147,16 +148,16 @@ init_cygheap::init_installation_root () PWCHAR p = installation_root; if (wcsncasecmp (p, L"\\\\", 2)) /* Normal drive letter path */ { - p = wcpcpy (p, L"\\??\\"); - GetModuleFileNameW (cygwin_hmodule, p, PATH_MAX - 4); + memmove (p + 4, p, PATH_MAX - 4); + p = wcpncpy (p, L"\\\\?\\", 4); } else { bool unc = false; if (wcsncmp (p + 2, L"?\\", 2)) /* No long path prefix, so UNC path. */ { - p = wcpcpy (p, L"\\??\\UN"); - GetModuleFileNameW (cygwin_hmodule, p, PATH_MAX - 6); + memmove (p + 6, p, PATH_MAX - 6); + p = wcpncpy (p, L"\\??\\UN", 6); *p = L'C'; unc = true; } @@ -175,6 +176,7 @@ init_cygheap::init_installation_root () RtlInt64ToHexUnicodeString (hash_path_name (0, installation_root), &installation_key, FALSE); + /* Strip off last path component ("\\cygwin1.dll") */ PWCHAR w = wcsrchr (installation_root, L'\\'); if (w) { @@ -185,13 +187,11 @@ init_cygheap::init_installation_root () api_fatal ("Can't initialize Cygwin installation root dir.\n" "Invalid DLL path"); - /* Remove "." from DLL search path and install our /bin dir instead. - Note that this change is propagated to child processes so we don't - have to call SetDllDirectory in each process. */ - installation_root[1] = L'\\'; - if (!SetDllDirectoryW (installation_root)) - debug_printf ("Couldn't set %W as DLL directory, %E", installation_root); - installation_root[1] = L'?'; + /* Copy result into installation_dir before stripping off "bin" dir and + revert to Win32 path. This path is used in cygheap_init to call + SetDllDirectory. */ + wcpncpy (installation_dir, installation_root, PATH_MAX); + installation_dir[1] = L'\\'; /* If w < p, the Cygwin DLL resides in the root dir of a drive or network path. In that case, if we strip off yet another backslash, the path @@ -213,8 +213,7 @@ init_cygheap::init_installation_root () if (cygwin_props.disable_key) { installation_key.Length = 0; - installation_key.Buffer[0] = L'\0'; - } + installation_key.Buffer[0] = L'\0'; } } void __stdcall @@ -257,6 +256,18 @@ cygheap_init () cygheap->init_tls_list (); } +/* Initial Cygwin heap setup. + Called by root process of a Cygwin process tree. */ +void +setup_cygheap () +{ + cygheap_init (); + cygheap->user.init (); + cygheap->init_installation_root (); /* Requires user.init! */ + cygheap->set_dll_dir (); + cygheap->pg.init (); +} + #define nextpage(x) ((char *) roundup2 ((uintptr_t) (x), \ wincap.allocation_granularity ())) #define allocsize(x) ((SIZE_T) nextpage (x)) diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h index c2f60e94d..55f26ed36 100644 --- a/winsup/cygwin/cygheap.h +++ b/winsup/cygwin/cygheap.h @@ -505,6 +505,7 @@ struct init_cygheap: public mini_cygheap unsigned bucket_val[NBUCKETS]; char *buckets[NBUCKETS]; WCHAR installation_root[PATH_MAX]; + WCHAR installation_dir[PATH_MAX]; UNICODE_STRING installation_key; WCHAR installation_key_buf[18]; cygheap_root root; @@ -533,6 +534,15 @@ struct init_cygheap: public mini_cygheap hook_chain hooks; void close_ctty (); void init_installation_root (); + void set_dll_dir () + { + /* Call SetDllDirectory on installation_dir. This removes "." from the + DLL search path and installs our /bin dir instead. + Amazing but true: This setting is propagated to child processes :-) + but only starting with Windows 8 :-( */ + if (!SetDllDirectoryW (installation_dir)) + debug_printf ("SetDllDirectoryW (%W), %E", installation_dir); + } void __reg1 init_tls_list ();; void __reg2 add_tls (_cygtls *); void __reg3 remove_tls (_cygtls *, DWORD); @@ -666,4 +676,5 @@ class cygheap_fdenum : public cygheap_fdmanip void __stdcall cygheap_fixup_in_child (bool); void __stdcall cygheap_init (); +void setup_cygheap (); extern char _cygheap_start[] __attribute__((section(".idata"))); diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index ac741a689..930397f06 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -609,7 +609,7 @@ void child_info_fork::handle_fork () { cygheap_fixup_in_child (false); - memory_init (false); + memory_init (); myself.thisproc (NULL); myself->uid = cygheap->user.real_uid; myself->gid = cygheap->user.real_gid; @@ -663,7 +663,7 @@ child_info_spawn::handle_spawn () if (!dynamically_loaded || get_parent_handle ()) { cygheap_fixup_in_child (true); - memory_init (false); + memory_init (); } if (!moreinfo->myself_pinfo || !DuplicateHandle (GetCurrentProcess (), moreinfo->myself_pinfo, @@ -769,7 +769,8 @@ dll_crt0_0 () if (!child_proc_info) { - memory_init (true); + setup_cygheap (); + memory_init (); #ifndef __x86_64__ /* WOW64 process on XP/64 or Server 2003/64? Check if we have been started from 64 bit process and if our stack is at an unusual diff --git a/winsup/cygwin/dlfcn.cc b/winsup/cygwin/dlfcn.cc index 2c74a1497..7462bc23c 100644 --- a/winsup/cygwin/dlfcn.cc +++ b/winsup/cygwin/dlfcn.cc @@ -166,10 +166,10 @@ dlopen (const char *name, int flags) { /* This may indicate that a dependent DLL could not be loaded. Typically this occurs because we removed the CWD from the - DLL search path via SetDllDirectory - (see init_cygheap::init_installation_root), and the load - mechanism expects that dlopening a DLL from the CWD allows - to load dependent DLLs from the same dir. + DLL search path via SetDllDirectory (see inline function + init_cygheap::set_dll_dir), and the load mechanism expects + that dlopening a DLL from the CWD allows to load dependent + DLLs from the same dir. To continue supporting this scenario, call LoadLibraryEx with the LOAD_WITH_ALTERED_SEARCH_PATH flag. This flag diff --git a/winsup/cygwin/shared.cc b/winsup/cygwin/shared.cc index 9f1f27cd9..4510d02ab 100644 --- a/winsup/cygwin/shared.cc +++ b/winsup/cygwin/shared.cc @@ -343,17 +343,8 @@ shared_info::initialize () } void -memory_init (bool init_cygheap) +memory_init () { - /* Initialize the Cygwin heap, if necessary */ - if (init_cygheap) - { - cygheap_init (); - cygheap->user.init (); - cygheap->init_installation_root (); /* Requires user.init! */ - cygheap->pg.init (); - } - shared_info::create (); /* Initialize global shared memory */ user_info::create (false); /* Initialize per-user shared memory */ /* Initialize tty list session stuff. Doesn't really belong here but diff --git a/winsup/cygwin/shared_info.h b/winsup/cygwin/shared_info.h index 6733b3636..90b386fe6 100644 --- a/winsup/cygwin/shared_info.h +++ b/winsup/cygwin/shared_info.h @@ -75,7 +75,7 @@ enum shared_locations }; -void __reg1 memory_init (bool); +void memory_init (); void __stdcall shared_destroy (); #define shared_align_past(p) \