From ecd339d1b4225627ecb371ed66d43139766fd4a8 Mon Sep 17 00:00:00 2001 From: Tuncer Ayaz Date: Fri, 15 Jan 2010 17:42:09 +0100 Subject: Don't return a false {error,eexist} in filelib:ensure_dir/1 This is about the non-atomicity of filelib:ensure_dir/1. When using filelib:ensure_dir/1 from multiple processes to create the same path or parts of the same directory structure (which happens with rebar's worker processes) it happens quite a lot that between a file:read_file_info/1 and file:make_dir/1 one of the other procs has already created the directory we want to create. mkdir(1) says one of the following for -p depending on which Unix like system you're on: "no error if existing" "no error will be reported if a directory given as an operand already exists" I've seen more than one Erlang project where the return value of ensure_dir/1 is ignored completely. To eliminate the race condition, call file:make_dir/1 without first testing whether the directory exists. If it succeeds everything is fine. Otherwise, if the error code is {error,eexists}, check whether the directory exists. If it does, everything is fine; if not, return {error,eexist} (which indicates that there exists a regular file with the same name, or (more unlikely) that another process removed the directory after the call to file:make_dir/1). Signed-off-by: Tuncer Ayaz --- lib/stdlib/src/filelib.erl | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/stdlib/src/filelib.erl b/lib/stdlib/src/filelib.erl index d65588f0d1..3acc40ea20 100644 --- a/lib/stdlib/src/filelib.erl +++ b/lib/stdlib/src/filelib.erl @@ -228,7 +228,17 @@ ensure_dir(F) -> ok; false -> ensure_dir(Dir), - file:make_dir(Dir) + case file:make_dir(Dir) of + {error,eexist}=EExist -> + case do_is_dir(Dir, file) of + true -> + ok; + false -> + EExist + end; + Err -> + Err + end end. -- cgit v1.2.3