mkdir的原子性

时间:2018-01-04 12:17:57

标签: tcl nfs mkdir

我在NFS v3文件系统上遇到一个奇怪的问题(我觉得这很重要)并行运行两个进程(按照下面的评论和我自己的知识,我认为语言不重要,我认为这足够可读了):

if { ! [file isdirectory $dir]} {
    if {[catch { file mkdir $dir} err]} {
        error "-E- failed to mkdir $dir: $err"
    }
} 

对于那些不熟悉的人,tcl中的file mkdirmkdir -p非常相似 - 只有当目录存在且不是目录时才会失败。我几乎100%(没有100%)在任何进程中都没有创建该文件,只有file mkdir。问题并不总是发生,但经常在运行我们的回归时我们可能会遇到:

Error: can't create directory "$dir": file already exists

如果在file mkdir处理$dir期间是现有的非目录文件,则应该。两个问题,第一个对我来说更重要:

  1. mkdir在这里不是原子的吗?特别是文件系统中的文件节点是否可以在创建期间的任何时间内作为非目录存在?
  2. 假设这确实是错误,有没有简单的原子方法来做到这一点?我想过exec mkdir -p,但如果我是对的,那将会遇到同样的问题。
  3. 重现这一点很难,所以在尝试修复之前我宁愿尽可能地确定。我跟随hintnfs FS可能是问题后来到这里,但我需要更多的专家建议。我不在乎两者是否成功,我只是不希望它们失败(第一次尝试)。

    最后的注释

    我在很长一段时间后回到了这里 - 而且这确实是一个tcl问题,但不仅仅是在nfs上,虽然nfs似乎让它变得更糟!。

    仍在寻找解释为什么我看到我所看到的答案的答案 - 请参阅答案。

    将此作为错误

    打开

    https://core.tcl.tk/tcl/tktview/270f78ca95b642fbed81ed03ad381d64a0d0f7df

    错误已修复!

    tcl核心的人很快!

1 个答案:

答案 0 :(得分:1)

在我发布错误的第二天,TCL核心的男孩和女孩已修复此问题!

https://core.tcl.tk/tcl/tktview/270f78ca95b642fbed81ed03ad381d64a0d0f7df

已修复1c12ee9e45222d6c

感谢mrcalvin的建议。


旧的测试尝试:

过了一会儿,我回过头来,并进行了以下测试(在ext4上):

两个带有tclsh 的终端:

1: while {1} {file mkdir bla}
2: while {1} {file mkdir bla; file delete bla}

最终在1:上出现错误:

can't create directory "bla": no such file or directory

两个带有tclsh 的终端:

1: while {1} {exec mkdir -p bla}
2: while {1} {exec mkdir -p bla; file delete bla}

没有错误。

一个终端重击一个tclsh

1: while [ 1 ]; do mkdir -p bla; done
2: while {1} {file mkdir bla; file delete bla}

最终我上了1:

mkdir: cannot create directory ‘bla’: File exists

足够

1: while [ 1 ]; do mkdir -p bla; rm -rf bla; done
2: while {1} {file mkdir bla}

没有错误(是罪魁祸首吗?)和

1: while [ 1 ]; do mkdir -p bla; done
2: while {1} {exec mkdir -p bla; file delete bla}

出错的可能性要小得多(因此删除不是很糟糕吗?)。当然,两个bash壳不会冲突:

1: while [ 1 ]; do mkdir -p bla; rm -rf bla; done
2: while [ 1 ]; do mkdir -p bla; done

在NFS上但不在EXT4上

1: while {1} {file mkdir bla; exec rm -rf bla}
2: while {1} {file mkdir bla}

失败

can't create directory "bla": file already exists

(随机)在1: 2:上。

结论

file mkdir并不像我想象的那么“薄”,并且可以产生竞态条件,其中一个mkdir认为正在创建的目录是一个文件。 file delete也可能有此问题或类似问题。它可能也对我的测试失败有所帮助,但对我最初的问题却没有帮助-对于NFS系统而言,情况变得更糟,其中file mkdir本身很容易重现错误。

解决方案是使用exec mkdir -p。到目前为止,这一切对我们都有效。