这可能是一个愚蠢的问题,但我只是看不到它。
我正在创建一个gmake
生成文件来构建我们的系统,如in this question所述。我希望makefile能够同时构建调试版本和发布版本(也许是一个很大的错误,但让我们将它分开)。一如既往,棘手的部分是构建依赖关系。现在,我正在让两个版本重建依赖项文件,并使用sed
使每个依赖项文件同时使用debug&发布版本。
代码类似于以下内容:
(flock 200 ; umask 002 ; $(FORTRAN) $(STD_FOR_OPTS) -O2 \
-gen-dep=$(task_SRCDIR)$(<F).d $(INCLUDEPATH) $(FFLAGS) -c $< -o $@ ; \
sed -e [stuff to remove a pesky abberent line] \
-i $(task_SRCDIR)$(<F).d; \
flock -s 200 ; flock -x 201 ; cp $(task_SRCDIR)$(<F).d $(task_DEPDIR)$(<F).d; \
sed -e [fairly standard dependency editing per various sources] \
< $(task_SRCDIR)$(<F).d >> $(task_DEPDIR)$(<F).d; \
rm -f $(task_SRCDIR)$(<F).d) \
200>$(task_SRCDIR)$(<F).d 201>$(task_DEPDIR)$(<F).d
(-gen-dep
选项来自我们必须使用的英特尔编译器套件。)
通常,一切都可以找到。 sed
命令执行正确的编辑,所有这些命令都适用于世界......除了发生死锁的罕见,不可预测的情况。此代码同时针对调试运行(尽管使用-g -debug
而不是-O2
),并使用静态模式规则和绝对目录发布版本。
如果我使用make -j 4 all
调用makefile,我会同时停止两个flock 200
语句(不 flock -s 200
根据ps -O cmd
)如果两者之间存在内核级竞争条件。调用shell的目标是相同的.d
文件,这是有道理的,因为它们是应该使用它们的唯一两个文件。但是,我不明白为什么一个flock 200
没有获得批准,但两者都是封锁的。
所有文件都在同一个本地文件系统上;没有涉及NFS flakiness(至少目前没有)。
忽略了以不同方式做出依赖关系的明显决策(无论如何我都在考虑这种情况),使用模板(后面的另一个考虑因素)等等,flock 200
如何在这里陷入僵局?
编辑我刚刚阅读了以下here:
最后,如果锁定文件被删除,即使某些东西持有旧锁,后续锁定尝试也会成功。因此,如果您要保护对任意资源的访问权限,请注意锁定文件的访问控制权限。您不希望任何人从您下面删除该文件。
也许我应该在flock -u 200
之后明确rm ...
?