Add exponential backoff to rmdir() on Windows

This commit is contained in:
Justine Tunney 2021-01-29 21:46:23 -08:00
parent bf8b1623c8
commit eaca5b3e81
7 changed files with 38 additions and 16 deletions

View file

@ -25,8 +25,9 @@ textwindows int chdir$nt(const char *path) {
int len;
char16_t path16[PATH_MAX];
if ((len = __mkntpath(path, path16)) == -1) return -1;
if (path16[len - 1] != u'/' && path16[len - 1] != u'\\') {
path16[len + 0] = u'/';
if (path16[len - 1] != u'\\') {
if (len + 1 + 1 > PATH_MAX) return enametoolong();
path16[len + 0] = u'\\';
path16[len + 1] = u'\0';
}
if (SetCurrentDirectory(path16)) {

View file

@ -92,10 +92,8 @@ static textwindows noinline DIR *opendir$nt(const char *name) {
char16_t name16[PATH_MAX];
if ((len = __mkntpath(name, name16)) == -1) return NULL;
if (len + 2 + 1 > PATH_MAX) return PROGN(enametoolong(), NULL);
if (name16[len - 1] == u'/' || name16[len - 1] == u'\\') {
name16[--len] = u'\0';
}
name16[len++] = u'/';
while (name16[len - 1] == u'\\') name16[--len] = u'\0';
name16[len++] = u'\\';
name16[len++] = u'*';
name16[len] = u'\0';
if (!(res = calloc(1, sizeof(DIR)))) return NULL;

View file

@ -17,15 +17,34 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/nt/errors.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/nt/synchronization.h"
#include "libc/sysv/errfuns.h"
textwindows int rmdir$nt(const char *path) {
uint16_t path16[PATH_MAX];
if (__mkntpath(path, path16) == -1) return -1;
if (RemoveDirectory(path16)) {
return 0;
} else {
return __winerr();
int e, ms, len;
char16_t path16[PATH_MAX];
if ((len = __mkntpath(path, path16)) == -1) return -1;
while (path16[len - 1] == u'\\') path16[--len] = u'\0';
if (len + 2 + 1 > PATH_MAX) return enametoolong();
for (ms = 1;; ms *= 2) {
if (RemoveDirectory(path16)) return 0;
/*
* Files can linger, for absolutely no reason.
* Possibly some Windows Defender bug on Win7.
* Sleep for up to one second w/ expo backoff.
* Alternative is use Microsoft internal APIs.
* Never could have imagined it'd be this bad.
*/
if ((e = GetLastError()) == kNtErrorDirNotEmpty && ms <= 512) {
Sleep(ms);
continue;
} else {
break;
}
}
errno = e;
return -1;
}

View file

@ -30,6 +30,5 @@
int touch(const char *file, uint32_t mode) {
int fd;
if ((fd = open(file, O_CREAT | O_WRONLY, mode)) == -1) return -1;
fsync(fd); /* TODO(jart): do we need it? */
return close(fd);
}