gpt4 book ai didi

linux - mkdir() 怎么会成功却设置了错误的权限呢?

转载 作者:IT王子 更新时间:2023-10-29 00:38:02 27 4
gpt4 key购买 nike

我对执行如下操作的一段 Linux 代码(用 C++ 编写)有疑问:

  1. 使用 mkdir("xyz",0755) 创建新目录成功(返回代码为 0)。
  2. 尝试在刚刚创建的目录中打开/创建一个新文件。
  3. 失败,因为新目录的权限实际上是 0600 而不是请求的 0755。

代码看起来像这样,并在进入此部分之前检查路径前缀“/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 是一个共享的,但也许不是完全隐藏的状态/变量。这是出了什么问题:

  1. 一个或多个线程正在执行上面的代码,愉快地创建目录。
  2. 与此同时,另一个线程正在摆弄 umask 以确保它正在创建的 Unix 套接字的正确权限,暂时将 umask 设置为 0177。
  3. 虽然 umask 摆弄的时间非常短,但墨菲定律规定目录有时恰好在 umask 为 0177 时创建,这也迫使目录获得权限掩码 0600 而不是 0755。

Lesson(重新)学习:当使用超过 1 个线程时,注意隐藏的共享状态/变量。

关于linux - mkdir() 怎么会成功却设置了错误的权限呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52279223/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com