diff --git a/LOG b/LOG index 5419c2092a..1075f8d5de 100644 --- a/LOG +++ b/LOG @@ -209,3 +209,40 @@ c/Mf.*nt - fixed unnessesary blocking in expeditor on Windows. c/expeditor.c +- eliminated a couple of thread-safety issues and limitations on the + sizes of pathnames produced by expansion of tilde (home-directory) + prefixes by replacing S_pathname, S_pathname_impl, and S_homedir + with S_malloc_pathname, which always mallocs space for the result. + one thread-safety issue involved the use of static strings for expanded + pathnames and affected various file-system operations. the other + affected the file open routines and involved use of the incoming + pathname while deactivated. the incoming pathname is sometimes if not + always a pointer into a Scheme bytevector, which can be overwritten if a + collection occurs while the thread is deactivated. the size limitation + corresponded to the use of the static strings, which were limited to + PATH_MAX bytes. (PATH_MAX typically isn't actually the maximum path + length in contemporary operating systems.) eliminated similar issues + for wide pathnames under Windows by adding S_malloc_wide_pathname. + consumers of the old routines have been modified to use the new + routines and to free the result strings. the various file operations + now consistently treat a pathname with an unresolvable home directory + as a pathname that happens to start with a tilde. eliminated unused + foreign-symbol binding of "(cs)pathname" to S_pathname. + io.c, externs.h, new_io.c, prim5.c, scheme.c, prim.c +- various places where a call to close or gzclose was retried when + the close operation was interrupted no longer do so, since this can + cause problems when another thread has reallocated the same file + descriptor. + new_io.c +- now using vcvarsall type x86_amd64 rather than amd64 when the + former appears to supported and the latter does not, as is the + case with VS Express 2015. + c/Mf-a6nt, c/Mf-ta6nt +- commented out one of the thread mats that consistently causes + indefinite delays under Windows and OpenBSD due to starvation. + thread.ms +- increased wait time for a couple of subprocess responses + 6.ms +- added call to collector to close files opened during iconv mats + specifically for when mats are run under Windows with no iconv dll. + io.ms diff --git a/c/Mf-a6nt b/c/Mf-a6nt index e4326ae050..4836cc918a 100644 --- a/c/Mf-a6nt +++ b/c/Mf-a6nt @@ -37,7 +37,10 @@ vs.bat: echo 'set INCLUDE=' >> $@ echo 'set LIB=' >> $@ echo 'set LIBPATH=' >> $@ - echo 'call "%VS140COMNTOOLS%..\..\VC\vcvarsall.bat" amd64' >> $@ + echo 'set MACHINETYPE=amd64' >> $@ + echo 'if exist "%VS140COMNTOOLS%..\..\VC\bin\x86_amd64\vcvarsx86_amd64.bat" set MACHINETYPE=x86_amd64' >> $@ + echo 'if exist "%VS140COMNTOOLS%..\..\VC\bin\vcvars64.bat" set MACHINETYPE=amd64' >> $@ + echo 'call "%VS140COMNTOOLS%..\..\VC\vcvarsall.bat" %MACHINETYPE%' >> $@ echo '%*' >> $@ chmod +x $@ diff --git a/c/Mf-ta6nt b/c/Mf-ta6nt index 78ab502507..2a823e5531 100644 --- a/c/Mf-ta6nt +++ b/c/Mf-ta6nt @@ -37,7 +37,10 @@ vs.bat: echo 'set INCLUDE=' >> $@ echo 'set LIB=' >> $@ echo 'set LIBPATH=' >> $@ - echo 'call "%VS140COMNTOOLS%..\..\VC\vcvarsall.bat" amd64' >> $@ + echo 'set MACHINETYPE=amd64' >> $@ + echo 'if exist "%VS140COMNTOOLS%..\..\VC\bin\x86_amd64\vcvarsx86_amd64.bat" set MACHINETYPE=x86_amd64' >> $@ + echo 'if exist "%VS140COMNTOOLS%..\..\VC\bin\vcvars64.bat" set MACHINETYPE=amd64' >> $@ + echo 'call "%VS140COMNTOOLS%..\..\VC\vcvarsall.bat" %MACHINETYPE%' >> $@ echo '%*' >> $@ chmod +x $@ diff --git a/c/externs.h b/c/externs.h index fa0c9828dc..5696a10e59 100644 --- a/c/externs.h +++ b/c/externs.h @@ -149,20 +149,20 @@ extern void S_intern_gensym PROTO((ptr g)); extern void S_retrofit_nonprocedure_code PROTO((void)); /* io.c */ -extern IBOOL S_file_existsp PROTO((const char *path, IBOOL followp)); -extern IBOOL S_file_regularp PROTO((const char *path, IBOOL followp)); -extern IBOOL S_file_directoryp PROTO((const char *path, IBOOL followp)); -extern IBOOL S_file_symbolic_linkp PROTO((const char *path)); -extern const char *S_pathname_impl PROTO((const char *inpath, char *buffer)); - +extern IBOOL S_file_existsp PROTO((const char *inpath, IBOOL followp)); +extern IBOOL S_file_regularp PROTO((const char *inpath, IBOOL followp)); +extern IBOOL S_file_directoryp PROTO((const char *inpath, IBOOL followp)); +extern IBOOL S_file_symbolic_linkp PROTO((const char *inpath)); #ifdef WIN32 extern ptr S_find_files PROTO((const char *wildpath)); #else -extern ptr S_directory_list PROTO((const char *path)); +extern ptr S_directory_list PROTO((const char *inpath)); #endif -extern const char *S_homedir PROTO((void)); -extern const char *S_pathname PROTO((const char *who, const char *inpath, IBOOL errorp, char *buf)); -extern IBOOL S_fixedpathp PROTO((const char *p)); +extern char *S_malloc_pathname PROTO((const char *inpath)); +#ifdef WIN32 +extern wchar_t *S_malloc_wide_pathname PROTO((const char *inpath)); +#endif +extern IBOOL S_fixedpathp PROTO((const char *inpath)); /* new-io.c */ extern INT S_gzxfile_fd PROTO((ptr x)); diff --git a/c/io.c b/c/io.c index 6261849853..9de2449711 100644 --- a/c/io.c +++ b/c/io.c @@ -33,172 +33,195 @@ static ptr s_wstring_to_bytevector PROTO((const wchar_t *s)); static ptr s_string_to_bytevector PROTO((const char *s)); #endif +/* raises an exception if insufficient space cannot be malloc'd. + otherwise returns a freshly allocated version of inpath with ~ (home directory) + prefix expanded, if possible */ +char *S_malloc_pathname(const char *inpath) { + char *outpath; const char *ip; + #ifdef WIN32 -/* Warning: returns pointer to static string */ -const char *S_homedir() { - static char home[PATH_MAX]; - const char *homedrive = getenv("HOMEDRIVE"); - const char *homepath = getenv("HOMEPATH"); + if (*inpath == '~' && (*(ip = inpath + 1) == 0 || DIRMARKERP(*ip))) { + const char *homedrive, *homepath; size_t n1, n2, n3; - if (snprintf(home, PATH_MAX, "%s%s", homedrive, homepath) < PATH_MAX) return home; - return NULL; -} -#else -/* Warning: returns pointer to static string */ -const char *S_homedir() { - const char *home; - static struct passwd *pwent; - - if ((home = getenv("HOME"))) return home; - if ((pwent = getpwuid(getuid()))) return pwent->pw_dir; - return NULL; -} -#endif - -const char *S_pathname_impl(const char *inpath, char *buffer) { - if (*inpath != '~') { return inpath; } - else { -#define setp(c) if (p > buffer + PATH_MAX) return NULL; else *p++ = (c) - static char path[PATH_MAX]; - char *p; - const char *ip, *dir; - - if (buffer == NULL) buffer = path; - - ip = inpath + 1; - if (*ip == 0 || DIRMARKERP(*ip)) { - if (!(dir = S_homedir())) return NULL; - } else { -#ifdef WIN32 - return inpath; -#else - struct passwd *pwent; - p = buffer; - while (*ip != 0 && !DIRMARKERP(*ip)) setp(*ip++); - setp(0); - if (!(pwent = getpwnam(buffer)) || !(dir = pwent->pw_dir)) - return NULL; -#endif /* WIN32 */ + if ((homedrive = getenv("HOMEDRIVE")) != NULL && (homepath = getenv("HOMEPATH")) != NULL) { + n1 = strlen(homedrive); + n2 = strlen(homepath); + n3 = strlen(ip) + 1; + if ((outpath = malloc(n1 + n2 + n3)) == NULL) S_error("expand_pathname", "malloc failed"); + memcpy(outpath, homedrive, n1); + memcpy(outpath + n1, homepath, n2); + memcpy(outpath + n1 + n2, ip, n3); + return outpath; } + } +#else /* WIN32 */ + if (*inpath == '~') { + const char *dir; size_t n1, n2; struct passwd *pwent; + if (*(ip = inpath + 1) == 0 || DIRMARKERP(*ip)) { + if ((dir = getenv("HOME")) == NULL) + if ((pwent = getpwuid(getuid())) != NULL) + dir = pwent->pw_dir; + } else { + char *userbuf; const char *user_start = ip; + do { ip += 1; } while (*ip != 0 && !DIRMARKERP(*ip)); + if ((userbuf = malloc(ip - user_start + 1)) == NULL) S_error("expand_pathname", "malloc failed"); + memcpy(userbuf, user_start, ip - user_start); + userbuf[ip - user_start] = 0; + dir = (pwent = getpwnam(userbuf)) != NULL ? pwent->pw_dir : NULL; + free(userbuf); + } + if (dir != NULL) { + n1 = strlen(dir); + n2 = strlen(ip) + 1; + if ((outpath = malloc(n1 + n2)) == NULL) S_error("expand_pathname", "malloc failed"); + memcpy(outpath, dir, n1); + memcpy(outpath + n1, ip, n2); + return outpath; + } + } +#endif /* WIN32 */ - p = buffer; - while (*dir != 0) setp(*dir++); - while (*ip != 0) setp(*ip++); - setp(0); - return buffer; -#undef setp + /* if no ~ or tilde dir can't be found, copy inpath */ + { + size_t n = strlen(inpath) + 1; + outpath = (char *)malloc(n); + memcpy(outpath, inpath, n); + return outpath; } } -/* Warning: may return pointer to static string */ -const char *S_pathname(const char *who, const char *inpath, - IBOOL errorp, char *buffer) { - const char *path = S_pathname_impl(inpath, buffer); - if (path != NULL) return path; - if (errorp) S_error1(who, "unable to expand path name ~s", Sstring(inpath)); - return inpath; -} - -IBOOL S_fixedpathp(p) const char *p; { - char c; - - p = S_pathname("", p, 0, (char *)0); - - if ((c = *p) == 0 || DIRMARKERP(c)) return 1; - if (c == '.') - return (c = *++p) == 0 - || DIRMARKERP(c) - || (c == '.' && ((c = *++p) == 0 || DIRMARKERP(c))); #ifdef WIN32 - if (*++p == ':') return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z'; +/* raises an exception if insufficient space cannot be malloc'd. + returns NULL if utf-8 path cannot be converted to wchars. + otherwise returns a freshly allocated, wide-character version + of inpath with ~ (home directory) prefix expanded, if possible */ +wchar_t *S_malloc_wide_pathname(const char *inpath) { + size_t n; char *path; wchar_t *wpath; + + path = S_malloc_pathname(inpath); + n = strlen(path) + 1; + /* counting on utf-8 representation having at least as many chars as wchar representation */ + if ((wpath = (wchar_t *)malloc(n * sizeof(wchar_t))) == NULL) { + free(path); + S_error("expand_pathname", "malloc failed"); + } + if (MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, (int)n) == 0) { + free(path); + free(wpath); + return NULL; + } + free(path); + return wpath; +} #endif - return 0; + +IBOOL S_fixedpathp(inpath) const char *inpath; { + char c; IBOOL res; char *path; + + path = S_malloc_pathname(inpath); + res = (c = *path) == 0 + || DIRMARKERP(c) +#ifdef WIN32 + || ((*(path + 1) == ':') && (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')) +#endif + || ((c == '.') + && ((c = *(path + 1)) == 0 + || DIRMARKERP(c) + || (c == '.' && ((c = *(path + 2)) == 0 || DIRMARKERP(c))))); + free(path); + return res; } -IBOOL S_file_existsp(path, followp) const char *path; IBOOL followp; { +IBOOL S_file_existsp(inpath, followp) const char *inpath; IBOOL followp; { #ifdef WIN32 - wchar_t wpath[PATH_MAX]; + wchar_t *wpath; IBOOL res; WIN32_FILE_ATTRIBUTE_DATA filedata; - path = S_pathname("file-exists?", path, 1, (char *)0); - if (MultiByteToWideChar(CP_UTF8,0,path,-1,wpath,PATH_MAX) == 0) + if ((wpath = S_malloc_wide_pathname(inpath)) == NULL) { return 0; - - return GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata); + } else { + res = GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata); + free(wpath); + return res; + } #else /* WIN32 */ - struct STATBUF statbuf; - const char *expandedpath = S_pathname("file-exists?", path, 0, (char *)0); + struct STATBUF statbuf; char *path; IBOOL res; - return (followp ? - STAT(expandedpath, &statbuf) : - LSTAT(expandedpath, &statbuf)) == 0; + path = S_malloc_pathname(inpath); + res = (followp ? STAT(path, &statbuf) : LSTAT(path, &statbuf)) == 0; + free(path); + return res; #endif /* WIN32 */ } -IBOOL S_file_regularp(path, followp) const char *path; IBOOL followp; { +IBOOL S_file_regularp(inpath, followp) const char *inpath; IBOOL followp; { #ifdef WIN32 - wchar_t wpath[PATH_MAX]; + wchar_t *wpath; IBOOL res; WIN32_FILE_ATTRIBUTE_DATA filedata; - path = S_pathname("file-regular?", path, 1, (char *)0); - if (MultiByteToWideChar(CP_UTF8,0,path,-1,wpath,PATH_MAX) == 0) + if ((wpath = S_malloc_wide_pathname(inpath)) == NULL) { return 0; - if (!GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata)) - return 0; - - return (filedata.dwFileAttributes & (FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT)) == 0; + } else { + res = GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata) + && (filedata.dwFileAttributes & (FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT)) == 0; + free(wpath); + return res; + } #else /* WIN32 */ - struct STATBUF statbuf; - const char *expandedpath = S_pathname("file-regular?", path, 0, (char *)0); + struct STATBUF statbuf; char *path; IBOOL res; - return (followp ? - STAT(expandedpath, &statbuf) : - LSTAT(expandedpath, &statbuf)) == 0 - && (statbuf.st_mode & S_IFMT) == S_IFREG; + path = S_malloc_pathname(inpath); + res = (followp ? STAT(path, &statbuf) : LSTAT(path, &statbuf)) == 0 + && (statbuf.st_mode & S_IFMT) == S_IFREG; + free(path); + return res; #endif /* WIN32 */ } -IBOOL S_file_directoryp(path, followp) const char *path; IBOOL followp; { +IBOOL S_file_directoryp(inpath, followp) const char *inpath; IBOOL followp; { #ifdef WIN32 - wchar_t wpath[PATH_MAX]; + wchar_t *wpath; IBOOL res; WIN32_FILE_ATTRIBUTE_DATA filedata; - path = S_pathname("file-directory?", path, 1, (char *)0); - if (MultiByteToWideChar(CP_UTF8,0,path,-1,wpath,PATH_MAX) == 0) + if ((wpath = S_malloc_wide_pathname(inpath)) == NULL) { return 0; - if (!GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata)) - return 0; - - return filedata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; + } else { + res = GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata) + && filedata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; + free(wpath); + return res; + } #else /* WIN32 */ - struct STATBUF statbuf; - const char *expandedpath = S_pathname("file-directory?", path, 0, (char *)0); + struct STATBUF statbuf; char *path; IBOOL res; - return (followp ? - STAT(expandedpath, &statbuf) : - LSTAT(expandedpath, &statbuf)) == 0 - && (statbuf.st_mode & S_IFMT) == S_IFDIR; + path = S_malloc_pathname(inpath); + res = (followp ? STAT(path, &statbuf) : LSTAT(path, &statbuf)) == 0 + && (statbuf.st_mode & S_IFMT) == S_IFDIR; + free(path); + return res; #endif /* WIN32 */ } -IBOOL S_file_symbolic_linkp(const char *path) { +IBOOL S_file_symbolic_linkp(const char *inpath) { #ifdef WIN32 - wchar_t wpath[PATH_MAX]; + wchar_t *wpath; IBOOL res; WIN32_FILE_ATTRIBUTE_DATA filedata; - path = S_pathname("file-symbolic-link?", path, 1, (char *)0); - if (MultiByteToWideChar(CP_UTF8,0,path,-1,wpath,PATH_MAX) == 0) + if ((wpath = S_malloc_wide_pathname(inpath)) == NULL) { return 0; - if (!GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata)) - return 0; - - return filedata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT; + } else { + res = GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata) + && filedata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT; + free(wpath); + return res; + } #else /* WIN32 */ - struct STATBUF statbuf; - const char *expandedpath = S_pathname("file-symbolic-link?", path, 0, (char *)0); + struct STATBUF statbuf; char *path; IBOOL res; - return (LSTAT(expandedpath, &statbuf) == 0) - && (statbuf.st_mode & S_IFMT) == S_IFLNK; + path = S_malloc_pathname(inpath); + res = LSTAT(path, &statbuf) == 0 && (statbuf.st_mode & S_IFMT) == S_IFLNK; + free(path); + return res; #endif /* WIN32 */ } @@ -213,22 +236,23 @@ static ptr s_wstring_to_bytevector(const wchar_t *s) { } ptr S_find_files(const char *wildpath) { - wchar_t wwildpath[PATH_MAX]; + wchar_t *wwildpath; intptr_t handle; struct _wfinddata_t fileinfo; - wildpath = S_pathname("directory-list", wildpath, 1, (char *)0); - if (MultiByteToWideChar(CP_UTF8,0,wildpath,-1,wwildpath,PATH_MAX) == 0) + if ((wwildpath = S_malloc_wide_pathname(wildpath)) == NULL) return S_LastErrorString(); - if ((handle = _wfindfirst(wwildpath, &fileinfo)) == (intptr_t)-1) + if ((handle = _wfindfirst(wwildpath, &fileinfo)) == (intptr_t)-1) { + free(wwildpath); return S_strerror(errno); - else { + } else { ptr ls = Snil; do { ls = Scons(s_wstring_to_bytevector(fileinfo.name), ls); } while (_wfindnext(handle, &fileinfo) == 0); _findclose(handle); + free(wwildpath); return ls; } } @@ -241,18 +265,21 @@ static ptr s_string_to_bytevector(const char *s) { return bv; } -ptr S_directory_list(const char *path) { - DIR *dirp; struct dirent *dep; ptr ls = Snil; +ptr S_directory_list(const char *inpath) { + char *path; DIR *dirp; - path = S_pathname("directory-list", path, 1, (char *)0); - - if ((dirp = opendir(path)) == (DIR *)0) + path = S_malloc_pathname(inpath); + if ((dirp = opendir(path)) == (DIR *)0) { + free(path); return S_strerror(errno); + } else { + struct dirent *dep; ptr ls = Snil; - while ((dep = readdir(dirp)) != (struct dirent *)0) - ls = Scons(s_string_to_bytevector(dep->d_name), ls); - - closedir(dirp); - return ls; + while ((dep = readdir(dirp)) != (struct dirent *)0) + ls = Scons(s_string_to_bytevector(dep->d_name), ls); + closedir(dirp); + free(path); + return ls; + } } #endif /* WIN32 */ diff --git a/c/new-io.c b/c/new-io.c index c276d0bb38..197c43d3a7 100644 --- a/c/new-io.c +++ b/c/new-io.c @@ -56,14 +56,36 @@ static INT lockfile PROTO((INT fd)); static ptr make_gzxfile PROTO((int fd, gzFile file)); /* - check: whether you want gzerror to be called on fd - (i.e. whether to double check if errors reported by 'ok' are real) + not_ok_is_fatal: !ok definitely implies error, so ignore gzerror ok: whether the result of body seems to be ok flag: will be set when an error is detected and cleared if no error fd: the gzFile object to call gzerror on body: the operation we are checking the error on */ #ifdef EINTR +/* like FD_EINTR_GUARD and GZ_EINTR_GUARD but ignores EINTR. + used for calls to close so we don't close a file descriptor that + might already have been reallocated by a different thread */ +#define FD_GUARD(ok,flag,body) \ + do { body; \ + flag = !(ok) && errno != EINTR; \ + } while (0) +#define GZ_GUARD(not_ok_is_fatal,ok,flag,fd,body) \ + do { body; \ + if (ok) { flag = 0; } \ + else { \ + INT errnum; \ + gzerror((fd),&errnum); \ + gzclearerr((fd)); \ + if (errnum == Z_ERRNO) { \ + flag = errno != EINTR; \ + } else { \ + flag = not_ok_is_fatal || errnum != Z_OK; \ + errno = 0; \ + } \ + } \ + } while (0) +/* like FD_GUARD and GZ_GUARD but spins on EINTR */ #define FD_EINTR_GUARD(ok,flag,body) \ do { body; \ if (ok) { flag = 0; break; } \ @@ -86,8 +108,8 @@ static ptr make_gzxfile PROTO((int fd, gzFile file)); } \ } while (1) #else /* EINTR */ -#define FD_EINTR_GUARD(ok,flag,body) do { body; flag = !(ok); } while (0) -#define GZ_EINTR_GUARD(not_ok_is_fatal,ok,flag,fd,body) \ +#define FD_GUARD(ok,flag,body) do { body; flag = !(ok); } while (0) +#define GZ_GUARD(not_ok_is_fatal,ok,flag,fd,body) \ do { body; \ if (ok) { flag = 0; } \ else { \ @@ -101,6 +123,8 @@ static ptr make_gzxfile PROTO((int fd, gzFile file)); } \ } \ } while (0) +#define FD_EINTR_GUARD FD_GUARD +#define GZ_EINTR_GUARD GZ_GUARD #endif /* EINTR */ #ifndef O_BINARY @@ -140,7 +164,8 @@ gzFile S_gzxfile_gzfile(ptr x) { return gzxfile_gzfile(x); } -ptr S_new_open_input_fd(const char *filename, IBOOL compressed) { +ptr S_new_open_input_fd(const char *infilename, IBOOL compressed) { + char *filename; INT saved_errno = 0; INT fd, dupfd, error, result, ok, flag; gzFile file; @@ -148,15 +173,17 @@ ptr S_new_open_input_fd(const char *filename, IBOOL compressed) { ptr tc = get_thread_context(); #endif - if ((filename = S_pathname_impl(filename, NULL)) == NULL) { - return Scons(FIX(OPEN_ERROR_OTHER), Sstring("failed to expand path name")); - } + filename = S_malloc_pathname(infilename); + /* NB: don't use infilename, which might point into a Scheme string, after this point */ DEACTIVATE(tc) FD_EINTR_GUARD(fd>=0, error, fd=OPEN(filename,O_BINARY|O_RDONLY,0)); saved_errno = errno; REACTIVATE(tc) + /* NB: don't use free'd filename after this point */ + free(filename); + if (error) { ptr str = S_strerror(saved_errno); switch (saved_errno) { @@ -175,13 +202,13 @@ ptr S_new_open_input_fd(const char *filename, IBOOL compressed) { if ((dupfd = DUP(fd)) == -1) { ptr str = S_strerror(errno); - FD_EINTR_GUARD(result == 0, error, result = CLOSE(fd)); + FD_GUARD(result == 0, error, result = CLOSE(fd)); return Scons(FIX(OPEN_ERROR_OTHER), str); } if ((file = gzdopen(dupfd, "rb")) == Z_NULL) { - FD_EINTR_GUARD(result == 0, error, result = CLOSE(fd)); - FD_EINTR_GUARD(result == 0, error, result = CLOSE(dupfd)); + FD_GUARD(result == 0, error, result = CLOSE(fd)); + FD_GUARD(result == 0, error, result = CLOSE(dupfd)); return Scons(FIX(OPEN_ERROR_OTHER), Sstring("unable to allocate compression state (too many open files?)")); } @@ -190,15 +217,15 @@ ptr S_new_open_input_fd(const char *filename, IBOOL compressed) { REACTIVATE(tc) if (compressed) { - FD_EINTR_GUARD(result == 0, error, result = CLOSE(fd)); + FD_GUARD(result == 0, error, result = CLOSE(fd)); /* box indicates gzip'd */ return Sbox(make_gzxfile(dupfd, file)); } - GZ_EINTR_GUARD(1, ok == 0 || ok == Z_BUF_ERROR, flag, file, ok = gzclose(file)); + GZ_GUARD(1, ok == 0 || ok == Z_BUF_ERROR, flag, file, ok = gzclose(file)); if (flag) {} /* make the compiler happy */ if (LSEEK(fd, 0, SEEK_SET) != 0) { /* gzdirect does not leave fd at position 0 */ - FD_EINTR_GUARD(result == 0, error, result = CLOSE(fd)); + FD_GUARD(result == 0, error, result = CLOSE(fd)); return Scons(FIX(OPEN_ERROR_OTHER),Sstring("unable to reset after reading header bytes")); } return MAKE_FD(fd); @@ -216,7 +243,7 @@ ptr S_compress_input_fd(INT fd, I64 pos) { } if ((file = gzdopen(dupfd, "rb")) == Z_NULL) { - FD_EINTR_GUARD(result == 0, error, result = CLOSE(dupfd)); + FD_GUARD(result == 0, error, result = CLOSE(dupfd)); return Sstring("unable to allocate compression state (too many open files?)"); } @@ -225,12 +252,12 @@ ptr S_compress_input_fd(INT fd, I64 pos) { REACTIVATE(tc) if (compressed) { - FD_EINTR_GUARD(result == 0, error, result = CLOSE(fd)); + FD_GUARD(result == 0, error, result = CLOSE(fd)); if (error) {} /* make the compiler happy */ return Sbox(make_gzxfile(dupfd, file)); } - GZ_EINTR_GUARD(1, ok == 0 || ok == Z_BUF_ERROR, flag, file, ok = gzclose(file)); + GZ_GUARD(1, ok == 0 || ok == Z_BUF_ERROR, flag, file, ok = gzclose(file)); if (flag) {} /* make the compiler happy */ if (LSEEK(fd, pos, SEEK_SET) != pos) { /* gzdirect does not leave fd at same position */ return Sstring("unable to reset after reading header bytes"); @@ -253,9 +280,10 @@ ptr S_compress_output_fd(INT fd) { } static ptr new_open_output_fd_helper( - const char *filename, INT mode, INT flags, + const char *infilename, INT mode, INT flags, IBOOL no_create, IBOOL no_fail, IBOOL no_truncate, IBOOL append, IBOOL lock, IBOOL replace, IBOOL compressed) { + char *filename; INT saved_errno = 0; iptr error; INT fd, result; @@ -269,9 +297,7 @@ static ptr new_open_output_fd_helper( (no_truncate ? 0 : O_TRUNC) | ((!append) ? 0 : O_APPEND); - if ((filename = S_pathname_impl(filename, NULL)) == NULL) { - return Scons(FIX(OPEN_ERROR_OTHER), Sstring("failed to expand path name")); - } + filename = S_malloc_pathname(infilename); if (replace && UNLINK(filename) != 0 && errno != ENOENT) { ptr str = S_strerror(errno); @@ -283,11 +309,15 @@ static ptr new_open_output_fd_helper( } } + /* NB: don't use infilename, which might point into a Scheme string, after this point */ DEACTIVATE(tc) FD_EINTR_GUARD(fd >= 0, error, fd = OPEN(filename, flags, mode)); saved_errno = errno; REACTIVATE(tc) + /* NB: don't use free'd filename after this point */ + free(filename); + if (error) { ptr str = S_strerror(saved_errno); switch (saved_errno) { @@ -308,7 +338,7 @@ static ptr new_open_output_fd_helper( saved_errno = errno; REACTIVATE(tc) if (error) { - FD_EINTR_GUARD(result == 0, error, result = CLOSE(fd)); + FD_GUARD(result == 0, error, result = CLOSE(fd)); return Scons(FIX(OPEN_ERROR_OTHER), S_strerror(saved_errno)); } } @@ -319,7 +349,7 @@ static ptr new_open_output_fd_helper( gzFile file = gzdopen(fd, append ? "ab" : "wb"); if (file == Z_NULL) { - FD_EINTR_GUARD(result == 0, error, result = CLOSE(fd)); + FD_GUARD(result == 0, error, result = CLOSE(fd)); return Scons(FIX(OPEN_ERROR_OTHER), Sstring("unable to allocate compression state")); } @@ -367,10 +397,10 @@ ptr S_close_fd(ptr file, IBOOL gzflag) { /* NOTE: close automatically releases locks so we don't to call unlock*/ DEACTIVATE(tc) if (!gzflag) { - FD_EINTR_GUARD(ok == 0, flag, ok = CLOSE(fd)); + FD_GUARD(ok == 0, flag, ok = CLOSE(fd)); } else { /* zlib 1.2.1 returns Z_BUF_ERROR when closing an empty file opened for reading */ - GZ_EINTR_GUARD(1, ok == 0 || ok == Z_BUF_ERROR, flag, gzfile, ok = gzclose(gzfile)); + GZ_GUARD(1, ok == 0 || ok == Z_BUF_ERROR, flag, gzfile, ok = gzclose(gzfile)); } saved_errno = errno; REACTIVATE(tc) diff --git a/c/prim.c b/c/prim.c index fb9e1b2883..518cb7dbd5 100644 --- a/c/prim.c +++ b/c/prim.c @@ -164,7 +164,6 @@ void S_prim_init() { create_c_entry_vector(); Sforeign_symbol("(cs)fixedpathp", (void *)S_fixedpathp); - Sforeign_symbol("(cs)pathname", (void *)S_pathname); Sforeign_symbol("(cs)bytes_allocated", (void *)S_compute_bytes_allocated); Sforeign_symbol("(cs)curmembytes", (void *)S_curmembytes); Sforeign_symbol("(cs)maxmembytes", (void *)S_maxmembytes); diff --git a/c/prim5.c b/c/prim5.c index 13f3690d9e..0818974a26 100644 --- a/c/prim5.c +++ b/c/prim5.c @@ -48,7 +48,7 @@ static ptr sorted_chunk_list PROTO((void)); static void s_showalloc PROTO((IBOOL show_dump, const char *outfn)); static ptr s_system PROTO((const char *s)); static ptr s_process PROTO((char *s, IBOOL stderrp)); -static I32 s_chdir PROTO((const char *s)); +static I32 s_chdir PROTO((const char *inpath)); static char *s_getwd PROTO((void)); static ptr s_set_code_byte PROTO((ptr p, ptr n, ptr x)); static ptr s_set_code_word PROTO((ptr p, ptr n, ptr x)); @@ -68,15 +68,15 @@ static ptr s_intern PROTO((ptr x)); static ptr s_intern2 PROTO((ptr x, ptr n)); static ptr s_strings_to_gensym PROTO((ptr pname_str, ptr uname_str)); static ptr s_intern3 PROTO((ptr x, ptr n, ptr m)); -static ptr s_delete_file PROTO((const char *path)); -static ptr s_delete_directory PROTO((const char *path)); -static ptr s_rename_file PROTO((const char *path1, const char *path2)); -static ptr s_mkdir PROTO((const char *path, INT mode)); -static ptr s_chmod PROTO((const char *path, INT mode)); -static ptr s_getmod PROTO((const char *path, IBOOL followp)); -static ptr s_path_atime PROTO((const char *path, IBOOL followp)); -static ptr s_path_ctime PROTO((const char *path, IBOOL followp)); -static ptr s_path_mtime PROTO((const char *path, IBOOL followp)); +static ptr s_delete_file PROTO((const char *inpath)); +static ptr s_delete_directory PROTO((const char *inpath)); +static ptr s_rename_file PROTO((const char *inpath1, const char *inpath2)); +static ptr s_mkdir PROTO((const char *inpath, INT mode)); +static ptr s_chmod PROTO((const char *inpath, INT mode)); +static ptr s_getmod PROTO((const char *inpath, IBOOL followp)); +static ptr s_path_atime PROTO((const char *inpath, IBOOL followp)); +static ptr s_path_ctime PROTO((const char *inpath, IBOOL followp)); +static ptr s_path_mtime PROTO((const char *inpath, IBOOL followp)); static ptr s_fd_atime PROTO((INT fd)); static ptr s_fd_ctime PROTO((INT fd)); static ptr s_fd_mtime PROTO((INT fd)); @@ -773,16 +773,18 @@ static ptr s_process(s, stderrp) char *s; IBOOL stderrp; { return LIST3(FIX(ifd), FIX(ofd), FIX(child)); } -static I32 s_chdir(const char *s) { - -#ifdef EINTR +static I32 s_chdir(const char *inpath) { + char *path; I32 status; - while ((status = CHDIR(S_pathname("current-directory", s, 1, (char *)0))) != 0 && errno == EINTR) ; - return status; + path = S_malloc_pathname(inpath); +#ifdef EINTR + while ((status = CHDIR(path)) != 0 && errno == EINTR) ; #else /* EINTR */ - return CHDIR(S_pathname("current-directory", s, 1, (char *)0)); + status = CHDIR(path); #endif /* EINTR */ + free(path); + return status; } #ifdef GETWD @@ -931,162 +933,203 @@ static ptr s_strings_to_gensym(ptr pname_str, ptr uname_str) { pname_str, uname_str); } -static ptr s_mkdir(const char *path, INT mode) { - INT status; - const char *expandedpath = S_pathname("mkdir", path, 1, (char *)0); +static ptr s_mkdir(const char *inpath, INT mode) { + INT status; ptr res; char *path; + path = S_malloc_pathname(inpath); #ifdef WIN32 - status = S_windows_mkdir(expandedpath); + status = S_windows_mkdir(path); #else /* WIN32 */ - status = mkdir(expandedpath, mode); + status = mkdir(path, mode); #endif /* WIN32 */ - return status == 0 ? Strue : S_strerror(errno); + res = status == 0 ? Strue : S_strerror(errno); + free(path); + return res; } -static ptr s_delete_file(const char *path) { - const char *extendedpath = S_pathname("delete-file", path, 1, (char *)0); - return UNLINK(extendedpath) == 0 ? Strue : S_strerror(errno); +static ptr s_delete_file(const char *inpath) { + ptr res; char *path; + + path = S_malloc_pathname(inpath); + res = UNLINK(path) == 0 ? Strue : S_strerror(errno); + free(path); + return res; } -static ptr s_delete_directory(const char *path) { - const char *extendedpath = S_pathname("delete-directory", path, 1, (char *)0); - return RMDIR(extendedpath) == 0 ? Strue : S_strerror(errno); +static ptr s_delete_directory(const char *inpath) { + ptr res; char *path; + + path = S_malloc_pathname(inpath); + res = RMDIR(path) == 0 ? Strue : S_strerror(errno); + free(path); + return res; } -static ptr s_rename_file(const char *path1, const char *path2) { - static char buf[PATH_MAX]; - const char *extendedpath1 = S_pathname("rename-file", path1, 1, buf); - const char *extendedpath2 = S_pathname("rename-file", path2, 1, (char *)0); - return RENAME(extendedpath1, extendedpath2) == 0 ? Strue : S_strerror(errno); +static ptr s_rename_file(const char *inpath1, const char *inpath2) { + ptr res; char *path1, *path2; + + path1 = S_malloc_pathname(inpath1); + path2 = S_malloc_pathname(inpath2); + res = RENAME(path1, path2) == 0 ? Strue : S_strerror(errno); + free(path1); + free(path2); + return res; } -static ptr s_chmod(const char *path, INT mode) { - INT status; - const char *extendedpath = S_pathname("chmod", path, 1, (char *)0); +static ptr s_chmod(const char *inpath, INT mode) { + ptr res; INT status; char *path; + path = S_malloc_pathname(inpath); #ifdef WIN32 /* pathetic approximation: (a) only handles user permissions, (b) doesn't handle execute permissions, (c) windows won't make file not readable */ - status = CHMOD(extendedpath, + status = CHMOD(path, (mode & 0400 ? S_IREAD : 0) | (mode & 0200 ? S_IWRITE : 0)); #else /* WIN32 */ - status = CHMOD(extendedpath, mode); + status = CHMOD(path, mode); #endif /* WIN32 */ - return status == 0 ? Strue : S_strerror(errno); + res = status == 0 ? Strue : S_strerror(errno); + free(path); + return res; } -static ptr s_getmod(const char *path, IBOOL followp) { - struct STATBUF statbuf; - const char *extendedpath = S_pathname("get-mode", path, 1, (char *)0); +static ptr s_getmod(const char *inpath, IBOOL followp) { + ptr res; char *path; struct STATBUF statbuf; + + path = S_malloc_pathname(inpath); /* according to msdn, user read/write bits are set according to the file's permission mode, and user execute bits are set according to the filename extension. it says nothing about group and other execute bits. */ - if ((followp ? STAT(extendedpath, &statbuf) : LSTAT(extendedpath, &statbuf)) != 0) - return S_strerror(errno); - - return FIX(statbuf.st_mode & 07777); + if ((followp ? STAT(path, &statbuf) : LSTAT(path, &statbuf)) != 0) { + res = S_strerror(errno); + } else { + res = FIX(statbuf.st_mode & 07777); + } + free(path); + return res; } -static ptr s_path_atime(const char *path, IBOOL followp) { +static ptr s_path_atime(const char *inpath, IBOOL followp) { #ifdef WIN32 - wchar_t wpath[PATH_MAX]; + ptr res; + wchar_t *wpath; WIN32_FILE_ATTRIBUTE_DATA filedata; __int64 total, sec; int nsec; - path = S_pathname("file-access-time", path, 1, (char *)0); - if (MultiByteToWideChar(CP_UTF8,0,path,-1,wpath,PATH_MAX) == 0) - return S_LastErrorString(); - if (!GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata)) { + if ((wpath = S_malloc_wide_pathname(inpath)) == NULL) { + res = S_LastErrorString(); + } else if (!GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata)) { DWORD err = GetLastError(); - return err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND ? - Sstring("no such file or directory") : - S_LastErrorString(); + res = err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND ? + Sstring("no such file or directory") : + S_LastErrorString(); + } else { + total = filedata.ftLastAccessTime.dwHighDateTime; + total <<= 32; + total |= filedata.ftLastAccessTime.dwLowDateTime; + sec = total / 10000000 - 11644473600L; + nsec = (total % 10000000) * 100; + res = Scons(Sinteger64(sec), Sinteger32(nsec)); } - - total = filedata.ftLastAccessTime.dwHighDateTime; - total <<= 32; - total |= filedata.ftLastAccessTime.dwLowDateTime; - sec = total / 10000000 - 11644473600L; - nsec = (total % 10000000) * 100; - return Scons(Sinteger64(sec), Sinteger32(nsec)); + free(wpath); + return res; #else /* WIN32 */ + ptr res; + char *path; struct STATBUF statbuf; - const char *extendedpath = S_pathname("file-access-time", path, 1, (char *)0); - if ((followp ? STAT(extendedpath, &statbuf) : LSTAT(extendedpath, &statbuf)) != 0) - return S_strerror(errno); - - return Scons(Sinteger64(SECATIME(statbuf)), Sinteger32(NSECATIME(statbuf))); + path = S_malloc_pathname(inpath); + if ((followp ? STAT(path, &statbuf) : LSTAT(path, &statbuf)) != 0) { + res = S_strerror(errno); + } else { + res = Scons(Sinteger64(SECATIME(statbuf)), Sinteger32(NSECATIME(statbuf))); + } + free(path); + return res; #endif /* WIN32 */ } -static ptr s_path_ctime(const char *path, IBOOL followp) { +static ptr s_path_ctime(const char *inpath, IBOOL followp) { #ifdef WIN32 - wchar_t wpath[PATH_MAX]; + ptr res; + wchar_t *wpath; WIN32_FILE_ATTRIBUTE_DATA filedata; __int64 total, sec; int nsec; - path = S_pathname("file-change-time", path, 1, (char *)0); - if (MultiByteToWideChar(CP_UTF8,0,path,-1,wpath,PATH_MAX) == 0) - return S_LastErrorString(); - if (!GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata)) { + if ((wpath = S_malloc_wide_pathname(inpath)) == NULL) { + res = S_LastErrorString(); + } else if (!GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata)) { DWORD err = GetLastError(); - return err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND ? - Sstring("no such file or directory") : - S_LastErrorString(); + res = err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND ? + Sstring("no such file or directory") : + S_LastErrorString(); + } else { + total = filedata.ftLastWriteTime.dwHighDateTime; + total <<= 32; + total |= filedata.ftLastWriteTime.dwLowDateTime; + sec = total / 10000000 - 11644473600L; + nsec = (total % 10000000) * 100; + res = Scons(Sinteger64(sec), Sinteger32(nsec)); } - - total = filedata.ftLastWriteTime.dwHighDateTime; - total <<= 32; - total |= filedata.ftLastWriteTime.dwLowDateTime; - sec = total / 10000000 - 11644473600L; - nsec = (total % 10000000) * 100; - return Scons(Sinteger64(sec), Sinteger32(nsec)); + free(wpath); + return res; #else /* WIN32 */ + ptr res; + char *path; struct STATBUF statbuf; - const char *extendedpath = S_pathname("file-change-time", path, 1, (char *)0); - if ((followp ? STAT(extendedpath, &statbuf) : LSTAT(extendedpath, &statbuf)) != 0) - return S_strerror(errno); - - return Scons(Sinteger64(SECCTIME(statbuf)), Sinteger32(NSECCTIME(statbuf))); + path = S_malloc_pathname(inpath); + if ((followp ? STAT(path, &statbuf) : LSTAT(path, &statbuf)) != 0) { + res = S_strerror(errno); + } else { + res = Scons(Sinteger64(SECCTIME(statbuf)), Sinteger32(NSECCTIME(statbuf))); + } + free(path); + return res; #endif /* WIN32 */ } -static ptr s_path_mtime(const char *path, IBOOL followp) { +static ptr s_path_mtime(const char *inpath, IBOOL followp) { #ifdef WIN32 - wchar_t wpath[PATH_MAX]; + ptr res; + wchar_t *wpath; WIN32_FILE_ATTRIBUTE_DATA filedata; __int64 total, sec; int nsec; - path = S_pathname("file-modification-time", path, 1, (char *)0); - if (MultiByteToWideChar(CP_UTF8,0,path,-1,wpath,PATH_MAX) == 0) - return S_LastErrorString(); - if (!GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata)) { + if ((wpath = S_malloc_wide_pathname(inpath)) == NULL) { + res = S_LastErrorString(); + } else if (!GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata)) { DWORD err = GetLastError(); - return err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND ? - Sstring("no such file or directory") : - S_LastErrorString(); + res = err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND ? + Sstring("no such file or directory") : + S_LastErrorString(); + } else { + total = filedata.ftLastWriteTime.dwHighDateTime; + total <<= 32; + total |= filedata.ftLastWriteTime.dwLowDateTime; + sec = total / 10000000 - 11644473600L; + nsec = (total % 10000000) * 100; + res = Scons(Sinteger64(sec), Sinteger32(nsec)); } - - total = filedata.ftLastWriteTime.dwHighDateTime; - total <<= 32; - total |= filedata.ftLastWriteTime.dwLowDateTime; - sec = total / 10000000 - 11644473600L; - nsec = (total % 10000000) * 100; - return Scons(Sinteger64(sec), Sinteger32(nsec)); + free(wpath); + return res; #else /* WIN32 */ + ptr res; + char *path; struct STATBUF statbuf; - const char *extendedpath = S_pathname("file-modification-time", path, 1, (char *)0); - if ((followp ? STAT(extendedpath, &statbuf) : LSTAT(extendedpath, &statbuf)) != 0) - return S_strerror(errno); - - return Scons(Sinteger64(SECMTIME(statbuf)), Sinteger32(NSECMTIME(statbuf))); + path = S_malloc_pathname(inpath); + if ((followp ? STAT(path, &statbuf) : LSTAT(path, &statbuf)) != 0) { + res = S_strerror(errno); + } else { + res = Scons(Sinteger64(SECMTIME(statbuf)), Sinteger32(NSECMTIME(statbuf))); + } + free(path); + return res; #endif /* WIN32 */ } diff --git a/c/scheme.c b/c/scheme.c index 049e68f183..205596b453 100644 --- a/c/scheme.c +++ b/c/scheme.c @@ -541,6 +541,7 @@ static IBOOL find_boot(name, ext, errorp) const char *name, *ext; IBOOL errorp; char pathbuf[PATH_MAX], buf[PATH_MAX]; uptr n; INT c; const char *path; + char *expandedpath; gzFile file; if (S_fixedpathp(name)) { @@ -551,7 +552,12 @@ static IBOOL find_boot(name, ext, errorp) const char *name, *ext; IBOOL errorp; path = name; - if (!(file = gzopen(S_pathname("", path, 0, (char *)0), "rb"))) { + expandedpath = S_malloc_pathname(path); + file = gzopen(expandedpath, "rb"); + /* assumption (seemingly true based on a glance at the source code): + gzopen doesn't squirrel away a pointer to expandedpath. */ + free(expandedpath); + if (!file) { if (errorp) { fprintf(stderr, "cannot open boot file %s\n", path); S_abnormal_exit(); @@ -621,7 +627,12 @@ static IBOOL find_boot(name, ext, errorp) const char *name, *ext; IBOOL errorp; } } - if (!(file = gzopen(S_pathname("", path, 0, (char *)0), "rb"))) { + expandedpath = S_malloc_pathname(path); + file = gzopen(expandedpath, "rb"); + /* assumption (seemingly true based on a glance at the source code): + gzopen doesn't squirrel away a pointer to expandedpath. */ + free(expandedpath); + if (!file) { if (verbose) fprintf(stderr, "trying %s...cannot open\n", path); continue; } diff --git a/mats/6.ms b/mats/6.ms index eb55ecdce8..b3587a69be 100644 --- a/mats/6.ms +++ b/mats/6.ms @@ -3457,14 +3457,14 @@ (begin (display "hello " (cadr p)) (flush-output-port (cadr p)) #t) - (begin (sleep (make-time 'time-duration 0 (if (embedded?) 3 1))) #t) ; wait for subprocess to catch up + (begin (sleep (make-time 'time-duration 0 3)) #t) ; wait for subprocess to catch up (char-ready? (car p)) (eq? (read (car p)) 'hello) (char-ready? (car p)) (char=? (read-char (car p)) #\space) (not (char-ready? (car p))) (begin (close-output-port (cadr p)) #t) - (begin (sleep (make-time 'time-duration 0 (if (embedded?) 3 1))) #t) ; wait for subprocess to catch up + (begin (sleep (make-time 'time-duration 0 3)) #t) ; wait for subprocess to catch up (sanitized-error? (write-char #\a (cadr p))) (sanitized-error? (write-char #\newline (cadr p))) (sanitized-error? (flush-output-port (cadr p))) diff --git a/mats/io.ms b/mats/io.ms index 0efade67e8..516b54d9e9 100644 --- a/mats/io.ms +++ b/mats/io.ms @@ -1040,6 +1040,11 @@ (define op (transcoded-port bp transcoder)) (newline op) (close-port op))) + ; NB: keep this last among the iconv-codec mats + ; close any files left open by failing iconv tests. this is particulary + ; important on windows when the iconv dll isn't available and where keeping + ; file open can prevent it from being reopened. + (begin (collect (collect-maximum-generation)) #t) )) (mat port-operations4 diff --git a/mats/thread.ms b/mats/thread.ms index d24675a519..991dff4386 100644 --- a/mats/thread.ms +++ b/mats/thread.ms @@ -1026,7 +1026,15 @@ (f (+ i 1)) (cons (+ (* i thread-count) j) (g (+ j 1)))))))))) ($thread-check) - (eqv? + ; this mat has some inherent starvation issues, with the main thread + ; looping rather than waiting on a condition at initialization time and + ; other threads looping rather than waiting on a condition when looking + ; for work to steal. these looping threads can hog the cpu without + ; doing anything useful, causing progress to stall or halt. this + ; manifests as occasional indefinite delays under Windows and OpenBSD, + ; and it has the potential to cause the same on other operating systems. + ; it's not clear how to fix the mat without changing it fundamentally. + #;(eqv? (let () ; from Ryan Newton (define-syntax ASSERT