From a5c0189bf6fc0a07fb930f279d949a95eb3dded7 Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Wed, 11 Sep 2024 00:52:34 -0700 Subject: [PATCH] Make vim startup faster It appears that GetFileAttributes(u"\\etc\\passwd") can take two seconds on Windows 10 at unpredictable times for reasons which are mysterious to me. Let's try avoiding that path entirely and pray to Microsoft it works --- libc/calls/fixenotdir.c | 10 ++++++++++ libc/calls/mkntpathat.c | 10 ++++------ libc/dlopen/dlopen.c | 10 +++++----- libc/intrin/getfileattributes.c | 5 +++-- third_party/musl/pwd.c | 5 +++-- 5 files changed, 25 insertions(+), 15 deletions(-) diff --git a/libc/calls/fixenotdir.c b/libc/calls/fixenotdir.c index 8787578a6..1537ea69c 100644 --- a/libc/calls/fixenotdir.c +++ b/libc/calls/fixenotdir.c @@ -23,10 +23,20 @@ #include "libc/nt/files.h" #include "libc/str/str.h" +static int IsAlpha(int c) { + return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z'); +} + static textwindows bool SubpathExistsThatsNotDirectory(char16_t *path) { char16_t *p; uint32_t attrs; while ((p = strrchr16(path, '\\'))) { + if (p == path) + // don't bother checking GetFileAttributes(u"\\") + break; + if (p == path + 2 && IsAlpha(path[0]) && path[1] == ':') + // don't bother checking GetFileAttributes(u"C:\\") + break; *p = u'\0'; if ((attrs = GetFileAttributes(path)) != -1u && !(attrs & kNtFileAttributeDirectory)) { diff --git a/libc/calls/mkntpathat.c b/libc/calls/mkntpathat.c index 1b9992704..a263cd838 100644 --- a/libc/calls/mkntpathat.c +++ b/libc/calls/mkntpathat.c @@ -75,6 +75,7 @@ static textwindows int __mkntpathath_impl(int64_t dirhand, const char *path, return n; } else { + filelen = __normntpath(file, filelen); return filelen; } } @@ -84,23 +85,20 @@ textwindows int __mkntpathath(int64_t dirhand, const char *path, int flags, // convert the path. int len; - if ((len = __mkntpathath_impl(dirhand, path, flags, file)) == -1) { + if ((len = __mkntpathath_impl(dirhand, path, flags, file)) == -1) return -1; - } // if path ends with a slash, then we need to manually do what linux // does and check to make sure it's a directory, and return ENOTDIR, // since WIN32 will reject the path with EINVAL if we don't do this. if (len && file[len - 1] == '\\') { uint32_t fattr; - if (len > 1 && !(len == 3 && file[1] == ':')) { + if (len > 1 && !(len == 3 && file[1] == ':')) file[--len] = 0; - } if ((fattr = GetFileAttributes(file)) != -1u && !(fattr & kNtFileAttributeReparsePoint) && - !(fattr & kNtFileAttributeDirectory)) { + !(fattr & kNtFileAttributeDirectory)) return enotdir(); - } } return len; diff --git a/libc/dlopen/dlopen.c b/libc/dlopen/dlopen.c index 03032ac3d..3f56cff8c 100644 --- a/libc/dlopen/dlopen.c +++ b/libc/dlopen/dlopen.c @@ -631,11 +631,11 @@ static dontinline bool foreign_compile(char exe[hasatleast PATH_MAX]) { errno = err; return false; } - while (waitpid(pid, &ws, 0) == -1) { - if (errno != EINTR) { - unlink(tmp); - return false; - } + if (waitpid(pid, &ws, 0) == -1) { + // signals and cancelation are blocked + // therefore this must be a real error + unlink(tmp); + return false; } if (ws) { unlink(tmp); diff --git a/libc/intrin/getfileattributes.c b/libc/intrin/getfileattributes.c index 976d0a2e3..67cb6808e 100644 --- a/libc/intrin/getfileattributes.c +++ b/libc/intrin/getfileattributes.c @@ -19,6 +19,7 @@ #include "libc/intrin/describeflags.h" #include "libc/intrin/strace.h" #include "libc/nt/files.h" +#include "libc/nt/runtime.h" #include "libc/nt/thunk/msabi.h" __msabi extern typeof(GetFileAttributes) *const __imp_GetFileAttributesW; @@ -30,7 +31,7 @@ __msabi extern typeof(GetFileAttributes) *const __imp_GetFileAttributesW; textwindows uint32_t GetFileAttributes(const char16_t *lpPathName) { uint32_t flags; flags = __imp_GetFileAttributesW(lpPathName); - NTTRACE("GetFileAttributes(%#hs) → %s", lpPathName, - DescribeNtFileFlagAttr(flags)); + NTTRACE("GetFileAttributes(%#hs) → {%s, %d}", lpPathName, + DescribeNtFileFlagAttr(flags), GetLastError()); return flags; } diff --git a/third_party/musl/pwd.c b/third_party/musl/pwd.c index fc54b77cf..3fb4203e2 100644 --- a/third_party/musl/pwd.c +++ b/third_party/musl/pwd.c @@ -91,8 +91,9 @@ __fopen_passwd(void) { FILE *f; char *s; - // MacOS has a fake /etc/passwd file without any user details. - if (!IsXnu() && (f = fopen("/etc/passwd", "rbe"))) + // MacOS has a fake /etc/passwd file without any user details + // GetFileAttributes(u"\\etc\\passwd") takes 2 seconds sometimes + if (!IsXnu() && !IsWindows() && (f = fopen("/etc/passwd", "rbe"))) return f; if (!(s = __create_synthetic_passwd_file())) return 0;