From a3d7036c36c4bee4f5345fa440b9d4c8635c3a94 Mon Sep 17 00:00:00 2001 From: Marius Gerbershagen Date: Sat, 1 Mar 2025 17:23:50 +0100 Subject: [PATCH] ensure-directories-exist: minor improvements Simply call mkdir and ignore EEXIST errors to prevent race conditions when two processes try to create a directory at the same time. Also avoids a redundant syscall since by not calling si::file-kind, so this should be slightly faster. --- src/c/unixfsys.d | 4 +++- src/cmp/proclamations.lsp | 2 +- src/lsp/mislib.lsp | 13 +++++++------ 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/c/unixfsys.d b/src/c/unixfsys.d index 058ef4edf..56a6e48ea 100644 --- a/src/c/unixfsys.d +++ b/src/c/unixfsys.d @@ -1193,7 +1193,9 @@ si_mkdir(cl_object directory, cl_object mode) #endif ecl_enable_interrupts(); - if (ecl_unlikely(ok < 0)) { + if (ok < 0 && errno == EEXIST) { + @(return ECL_NIL); + } else if (ecl_unlikely(ok < 0)) { cl_object c_error = _ecl_strerror(errno); const char *msg = "Could not create directory ~S" "~%C library error: ~S"; diff --git a/src/cmp/proclamations.lsp b/src/cmp/proclamations.lsp index 84bffce47..9e5eb594f 100644 --- a/src/cmp/proclamations.lsp +++ b/src/cmp/proclamations.lsp @@ -1114,7 +1114,7 @@ (proclamation ext:mkstemp (pathname-designator) (or null pathname)) (proclamation ext:copy-file (pathname-designator pathname-designator) gen-bool) -(proclamation si:mkdir (pathname-designator unsigned-byte) string) +(proclamation si:mkdir (pathname-designator unsigned-byte) (or string null)) (proclamation si:rmdir (pathname-designator) null) diff --git a/src/lsp/mislib.lsp b/src/lsp/mislib.lsp index 3502f5809..1638655fe 100644 --- a/src/lsp/mislib.lsp +++ b/src/lsp/mislib.lsp @@ -292,12 +292,13 @@ where CREATED is true only if we succeeded on creating all directories." (dolist (item (pathname-directory full-pathname)) (setf d (nconc d (list item))) (let* ((p (make-pathname :directory d :defaults *default-pathname-defaults*))) - (unless (or (symbolp item) (si::file-kind p nil)) - (setf created t) - (let ((ps (namestring p))) - (when verbose - (format t "~%;;; Making directory ~A" ps)) - (si::mkdir ps mode))))) + (unless (symbolp item) + (let* ((ps (namestring p)) + (newly-created (si::mkdir ps mode))) + (when newly-created + (setf created t) + (when verbose + (format t "~%;;; Making directory ~A" ps))))))) (values pathname created)))) (defmacro with-hash-table-iterator ((iterator package) &body body)