From bd7a591df17c38d6ce9f51e092364a98ed4c1d7b Mon Sep 17 00:00:00 2001 From: Todd Gamblin Date: Sun, 2 Jul 2017 17:49:08 -0700 Subject: Make filesytem more resilient to concurrent updates. - Uses O_CREAT for touch (for guaranteed atomic open on NFS, multi-node) - Ignore concurrent create errors in mkdirp --- lib/spack/llnl/util/filesystem.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/spack/llnl/util/filesystem.py b/lib/spack/llnl/util/filesystem.py index 88e000b6d3..7a9fb7b8ac 100644 --- a/lib/spack/llnl/util/filesystem.py +++ b/lib/spack/llnl/util/filesystem.py @@ -251,7 +251,11 @@ def mkdirp(*paths): """Creates a directory, as well as parent directories if needed.""" for path in paths: if not os.path.exists(path): - os.makedirs(path) + try: + os.makedirs(path) + except OSError as e: + if e.errno != errno.EEXIST or not os.path.isdir(path): + raise e elif not os.path.isdir(path): raise OSError(errno.EEXIST, "File already exists", path) @@ -291,8 +295,14 @@ def hide_files(*file_list): def touch(path): """Creates an empty file at the specified path.""" - with open(path, 'a'): + perms = (os.O_WRONLY | os.O_CREAT | os.O_NONBLOCK | os.O_NOCTTY) + fd = None + try: + fd = os.open(path, perms) os.utime(path, None) + finally: + if fd is not None: + os.close(fd) def touchp(path): -- cgit v1.2.3-70-g09d2