summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/path.cc50
1 files changed, 42 insertions, 8 deletions
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index ee7636dbf..16de025b6 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -4445,11 +4445,23 @@ cwdstuff::set (path_conv *nat_cwd, const char *posix_cwd)
{
/* On init, just reopen Win32 CWD with desired access flags.
We can access the PEB without lock, because no other thread
- can change the CWD. */
- RtlInitUnicodeString (&upath, L"");
- InitializeObjectAttributes (&attr, &upath,
- OBJ_CASE_INSENSITIVE | OBJ_INHERIT,
- peb.ProcessParameters->CurrentDirectoryHandle, NULL);
+ can change the CWD. However, there's a chance that the handle
+ is NULL, even though CurrentDirectoryName isn't so we have to
+ be careful. */
+ if (!peb.ProcessParameters->CurrentDirectoryHandle)
+ {
+ InitializeObjectAttributes (&attr,
+ &peb.ProcessParameters->CurrentDirectoryName,
+ OBJ_CASE_INSENSITIVE | OBJ_INHERIT, NULL, NULL);
+ }
+ else
+ {
+ RtlInitUnicodeString (&upath, L"");
+ InitializeObjectAttributes (&attr,
+ &upath, OBJ_CASE_INSENSITIVE | OBJ_INHERIT,
+ peb.ProcessParameters->CurrentDirectoryHandle,
+ NULL);
+ }
}
else
InitializeObjectAttributes (&attr, &upath,
@@ -4474,9 +4486,31 @@ cwdstuff::set (path_conv *nat_cwd, const char *posix_cwd)
}
if (!NT_SUCCESS (status))
{
- cwd_lock.release ();
- __seterrno_from_nt_status (status);
- return -1;
+ /* Called from chdir? Just fail. */
+ if (nat_cwd)
+ {
+ cwd_lock.release ();
+ __seterrno_from_nt_status (status);
+ return -1;
+ }
+ /* Otherwise we're in init and posix hasn't been set yet. Try to
+ duplicate the handle instead. If that fails, too, set dir to NULL
+ and carry on. This will at least set posix to some valid path at
+ process startup, and subsequent getcwd calls don't EFAULT. */
+ debug_printf ("WARNING: Can't reopen CWD %y '%S', status %y",
+ peb.ProcessParameters->CurrentDirectoryHandle,
+ &peb.ProcessParameters->CurrentDirectoryName,
+ status);
+ if (!peb.ProcessParameters->CurrentDirectoryHandle
+ || !DuplicateHandle (GetCurrentProcess (),
+ peb.ProcessParameters->CurrentDirectoryHandle,
+ GetCurrentProcess (), &h, 0, TRUE, 0))
+ {
+ cwd_lock.release ();
+ if (peb.ProcessParameters->CurrentDirectoryHandle)
+ debug_printf ("...and DuplicateHandle failed with %E.");
+ dir = NULL;
+ }
}
}
/* Set new handle. Note that we simply overwrite the old handle here