diff options
| author | kjnash <k.j.nash@usa.net> | 2018-09-15 18:41:23 (GMT) |
|---|---|---|
| committer | kjnash <k.j.nash@usa.net> | 2018-09-15 18:41:23 (GMT) |
| commit | d24a3eb2babc2868c7935f0815288c9ab02c3880 (patch) | |
| tree | 2ee6809fdc6448db53cbd12bb6e35df4fe077503 /generic/tclFCmd.c | |
| parent | 754bb107b4100f394d445d589dddc94e59dd2d04 (diff) | |
| parent | 9a15a1b58648809ffb208eaa00cd20af4784050d (diff) | |
| download | tcl-d24a3eb2babc2868c7935f0815288c9ab02c3880.zip tcl-d24a3eb2babc2868c7935f0815288c9ab02c3880.tar.gz tcl-d24a3eb2babc2868c7935f0815288c9ab02c3880.tar.bz2 | |
merge 8.6
Diffstat (limited to 'generic/tclFCmd.c')
| -rw-r--r-- | generic/tclFCmd.c | 54 |
1 files changed, 30 insertions, 24 deletions
diff --git a/generic/tclFCmd.c b/generic/tclFCmd.c index bb814ea..fda2940 100644 --- a/generic/tclFCmd.c +++ b/generic/tclFCmd.c @@ -240,9 +240,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. @@ -269,23 +273,25 @@ TclFileMakeDirsCmd( * subdirectory. */ - if (errno != EEXIST) { - errfile = target; - goto done; - } else 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; + if (errno == EEXIST) { + /* 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; + } + /* 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. */ @@ -363,14 +369,7 @@ TclFileDeleteCmd( */ if (Tcl_FSLstat(objv[i], &statBuf) != 0) { - /* - * Trying to delete a file that does not exist is not considered - * an error, just a no-op - */ - - if (errno != ENOENT) { - result = TCL_ERROR; - } + result = TCL_ERROR; } else if (S_ISDIR(statBuf.st_mode)) { /* * We own a reference count on errorBuffer, if it was set as a @@ -406,13 +405,20 @@ TclFileDeleteCmd( } if (result != TCL_OK) { - result = TCL_ERROR; /* + * Avoid possible race condition (file/directory deleted after call + * of lstat), so bypass ENOENT because not an error, just a no-op + */ + if (errno == ENOENT) { + result = TCL_OK; + continue; + } + /* * It is important that we break on error, otherwise we might end * up owning reference counts on numerous errorBuffers. */ - + result = TCL_ERROR; break; } } |
