From 51aecf205dab16072098f2f5119d6b9026f73e65 Mon Sep 17 00:00:00 2001 From: sebres Date: Mon, 9 Jul 2018 17:18:07 +0000 Subject: closes [270f78ca95b642fb]: fix the race condition for `file mkdir` if some worker deletes directory immediately after the succeded create inside 3rd worker. --- generic/tclFCmd.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/generic/tclFCmd.c b/generic/tclFCmd.c index 1363829..da15262 100644 --- a/generic/tclFCmd.c +++ b/generic/tclFCmd.c @@ -243,9 +243,13 @@ TclFileMakeDirsCmd( break; } for (j = 0; j < pobjc; j++) { + int errCount = 2; + target = Tcl_FSJoinPath(split, j + 1); Tcl_IncrRefCount(target); + createDir: + /* * Call Tcl_FSStat() so that if target is a symlink that points to * a directory we will create subdirectories in that directory. @@ -273,24 +277,24 @@ TclFileMakeDirsCmd( */ if (errno == EEXIST) { - if ((Tcl_FSStat(target, &statBuf) == 0) - && S_ISDIR(statBuf.st_mode)) { - /* - * It is a directory that wasn't there before, so keep - * going without error. - */ - - Tcl_ResetResult(interp); - } else { - errfile = target; - goto done; + /* Be aware other workers could delete it immediately after + * creation, so give this worker still one chance (repeat once), + * see [270f78ca95] for description of the race-condition. + * Don't repeat the create always (to avoid endless loop). */ + if (--errCount > 0) { + goto createDir; } - } else { - errfile = target; - goto done; + /* Already tried, with delete in-between directly after + * creation, so just continue (assume created successful). */ + goto nextPart; } + + /* return with error */ + errfile = target; + goto done; } + nextPart: /* * Forget about this sub-path. */ -- cgit v0.12