我有一个Linux代码(用C ++编写)的问题,它做了这样的事情:
代码如下所示,在进入此部分之前检查路径前缀“/ tmp / slim”是否存在:
int somefunc(const string& path)
{
if ( mkdir( path.c_str(), 0755 ) == 0 ) {
// (*) if (!access( path.c_str(), F_OK | R_OK | W_OK | X_OK ) == 0 )
// (*) chmod( path.c_str(), 0755);
string pidinfo = to_string( getpid() ) + "\n";
string pidinfofile = path + "/pid";
int fd = open( pidinfofile.c_str(), O_RDWR | O_CREAT, S_IWUSR | S_IRUSR );
if ( fd == -1 )
return 0;
ssize_t written = write( fd, text.c_str(), text.size() );
// ... do more stuff
}
}
由于这个strace片段(没有行丢失/编辑)显示,即使mkdir()返回0,openat()也会失败。
13661 16:32:22.068465 mkdir("/tmp/slim/testsock", 0755) = 0
13661 16:32:22.068720 getpid() = 13661
13661 16:32:22.068829 openat(AT_FDCWD, "/tmp/slim/testsock/pid", O_RDWR|O_CREAT, 0600) = -1 EACCES (Permission denied)
运行getfacl的结果如下所示:
[localhost]$ getfacl /tmp/slim/
getfacl: Removing leading '/' from absolute path names
# file: tmp/slim/
# owner: stk
# group: stk
user::rwx
group::r-x
other::r-x
mkdir()如何返回0但是创建一个具有与指定权限不同的权限的目录?它不是一个umask的东西,我尝试在创建目录之前将umask设置为0而没有任何影响。如果标有(*)的两条注释行被启用/取消注释,那么事情就会发挥作用 - 但我不喜欢那种能够解决真正问题的症状治疗方法。对于这种看似奇怪的行为,必须有一个合理的解释。
故事的一部分是,这适用于具有多个线程的应用程序。每个线程执行上面的代码(这是一个小的,线程安全的函数),并且大多数线程成功,但总是1或2(5-10中)失败,如上所述。
好吧,事实证明(并且非常期待,对吧?)正如@RobertHarvey也暗示的那样,这是一个线程问题。但我也有点正确:-)当我在评论中写道“某处存在一些隐藏的共享状态”。好吧,进程umask是一个共享的,但可能不是完全隐藏的状态/变量。这是出了什么问题:
课程(重新)学习:使用多个线程时注意隐藏的共享状态/变量。