天道酬勤,学无止境

依次使用 stat 和 mkdir 的竞争条件(Race condition with stat and mkdir in sequence)

问题
if (stat(DIR, &st) != 0) { if (mkdir(DIR, 0755) < 0) { return ERROR; } } if (mkdir(NDUID_DIR, 0755) < 0) { if(errno != EEXIST) { return ERROR; } }
回答1

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 如何在没有竞争条件的情况下重命名()?(How to rename() without race conditions?)
    问题 如果我想将A重命名为B ,但仅当B不存在时,天真的事情就是检查B存在(使用access("B", F_OK)或类似的东西),如果它不继续与rename 。 不幸的是,这会打开一个窗口,在此期间其他一些进程可能决定创建B ,然后它被覆盖 - 更糟糕的是,没有迹象表明曾经发生过类似的事情。 其他文件系统访问功能不受此影响 - open具有O_EXCL (因此复制文件是安全的),并且最近 Linux 获得了一整套*at系统调用,可以防止大多数其他竞争条件 - 但不是这个特定的( renameat存在) ,但可以防止出现完全不同的问题)。 那么它有解决方案吗? 回答1 从 Linux 内核 3.15(2014 年 6 月发布)开始,这可以通过 syscall(__NR_renameat2, AT_FDCWD, "source-file", AT_FDCWD, "dest-file", RENAME_NOREPLACE)(包括<syscall.h> , <fcntl.h> fcntl.h <syscall.h> ) <fcntl.h>和<linux/fs.h> )。 这比 link() 好,因为永远不会有两个文件名同时存在的点(特别是对于 link(),精确定时的断电可能导致两个文件名永远保留)。 glibc 2.28(2018 年 8 月发布)添加了一个 renameat2()
  • 带有 EEXIST 的 stat 与 mkdir(stat vs mkdir with EEXIST)
    问题 如果文件夹不存在,我需要创建文件夹,所以我使用: bool mkdir_if_not_exist(const char *dir) { bool ret = false; if (dir) { // first check if folder exists struct stat folder_info; if (stat(dir, &folder_info) != 0) { if (errno == ENOENT) { // create folder if (mkdir(dir, S_IRWXU | S_IXGRP | S_IRGRP | S_IROTH | S_IXOTH) ?!= 0) // 755 perror("mkdir"); else ret = true; } else perror("stat"); } else ret = true; ?// dir exists } return ret; } 该文件夹仅在程序第一次运行期间创建 - 之后它只是一个检查。 建议跳过 stat 调用并调用 mkdir 并根据 EEXIST 检查 errno。 它会带来真正的好处吗? 回答1 更重要的是,使用stat + mkdir方法,存在竞争条件:在stat和mkdir之间,另一个程序可以执行mkdir ,因此您的mkdir仍然可能因EEXIST失败。 回答2
  • Race condition with stat and mkdir in sequence
    Coverity complains of . toctou: Calling function mkdir that uses DIR after a check function. This can cause a time-of-check, time-of-use race condition if (stat(DIR, &st) != 0) { if (mkdir(DIR, 0755) < 0) { return ERROR; } } Is it good enough to change the code to ,I was using stat only for file exist check if (mkdir(NDUID_DIR, 0755) < 0) { if(errno != EEXIST) { return ERROR; } } Is there a better way to fix the code?
  • 带连接文件描述符的pthread竞争条件(pthread race condition with connection file descriptors)
    问题 我正在为学校作业实现一个简单的多线程Web服务器,并且遇到了一些同步问题,每个连接都使用了连接文件描述符。 我最初的问题是,一个线程有时会关闭文件描述符(conn_fd),因为该文件描述符也被另一个线程使用。 当另一个线程尝试send()或recv()时,这将导致错误的文件描述符错误。 我的解决方法是存储是否打开了每个文件描述符(最多1000个(我知道是任意数字,容易出错))。 如果accept()返回的文件描述符已经打开,我的程序将调用fcntl(conn_fd,F_DUPFD,0); 创建一个重复的文件描述符,以便一个线程不会无意间关闭另一个线程将需要使用的连接。 我的程序似乎比开始跟踪打开的文件描述符之前的性能要好,但是我仍然遇到一些同步问题,无法解决。 每个线程的开始路由中的conn_fd process_connection_request()似乎正在崩溃。 我在对服务器运行Siege时尝试使用Helgrind来隔离问题。 不幸的是,我的代码在Helgrind下运行时从未崩溃。 它的确表明了conn_fd的潜在竞争条件,但我认为将我周围拥有的互斥体包装在main()和process_connection_request()中都可以解决该问题。 我以前从未开发过任何多线程或套接字程序,而且我怀疑缺少一些简单的东西。
  • 附加到文件时如何避免竞争条件?(How do I avoid race conditions when appending to a file?)
    问题 我正在考虑使用 PipelineDB 进行分析。 数据仓库我希望所有的新的数据到一个文件,并追加tail -F成psql像网站上的例子。 我有多个数据源,所以为了获得确定性的结果,我想将它们全部附加到同一个输入文件中,它们将保持相同的顺序。 有没有一种简单的、惯用的方法来避免竞争条件? 像我可以将数据传输到的单文件服务器之类的东西? 编辑: 实际上,竞态条件正是我想要的。 但是每一行都必须是原子的,所以没有一行被破坏。 不过,行可以交错。 回答1 您可以使用 mkdir 模拟互斥锁,这是原子创建和检查操作(这是在内核级别确保的): # locking example -- CORRECT # Bourne lockdir=/tmp/myscript.lock if mkdir "$lockdir" then # directory did not exist, but was created successfully echo >&2 "successfully acquired lock: $lockdir" # continue script else echo >&2 "cannot acquire lock, giving up on $lockdir" exit 0 fi 有关更多信息(和其他解决方案),请查看常见问题解答: http://mywiki
  • flock():在没有竞争条件的情况下删除锁定的文件?(flock(): removing locked file without race condition?)
    问题 我正在将flock()用于名为互斥的进程间(即某些进程可以决定对“ some_name”进行锁定),这是通过将临时目录中名为“ some_name”的文件锁定来实现的: lockfile = "/tmp/some_name.lock"; fd = open(lockfile, O_CREAT); flock(fd, LOCK_EX); do_something(); unlink(lockfile); flock(fd, LOCK_UN); 应在某个时候删除锁定文件,以避免用数百个文件填充temp目录。 但是,此代码中存在明显的竞争条件。 进程A,B和C的示例: A opens file A locks file B opens file A unlinks file A unlocks file B locks file (B holds a lock on the deleted file) C opens file (a new file one is created) C locks file (two processes hold the same named mutex !) 有没有办法在不引入这种竞争条件的情况下删除锁定文件? 回答1 对不起,如果我回答一个死的问题: 锁定文件后,打开它的另一个副本,fstat两个副本并检查inode编号,如下所示:
  • 如何在C ++ / Linux中创建目录树?(How can I create directory tree in C++/Linux?)
    问题 我想要一种简单的方法来在C ++ / Linux中创建多个目录。 例如,我想在目录中保存文件lola.file: /tmp/a/b/c 但是如果目录不存在,我希望它们可以自动创建。 一个有效的例子将是完美的。 回答1 在C ++ 17或更高版本中,存在具有函数std :: filesystem :: create_directories的标准头<filesystem> ,应在现代C ++程序中使用。 但是,C ++标准函数没有特定于POSIX的显式权限(模式)参数。 但是,这是一个可以用C ++编译器编译的C函数。 /* @(#)File: mkpath.c @(#)Purpose: Create all directories in path @(#)Author: J Leffler @(#)Copyright: (C) JLSS 1990-2020 @(#)Derivation: mkpath.c 1.16 2020/06/19 15:08:10 */ /*TABSTOP=4*/ #include "posixver.h" #include "mkpath.h" #include "emalloc.h" #include <errno.h> #include <string.h> /* "sysstat.h" == <sys/stat.h> with fixup for
  • 在检查文件是否存在然后创建它时如何避免竞争条件?(How to avoid race condition when checking if file exists and then creating it?)
    问题 我正在考虑代码中的极端情况,当您检查文件是否存在时,我无法弄清楚如何避免问题,如果不存在,则使用该文件名创建一个文件。 代码大致如下所示: // 1 status = stat(filename); if (!status) { // 2 create_file(filename); } 在调用 1 和 2 之间,另一个进程可以创建文件名。 如何避免这个问题,是否有针对此类问题的通用解决方案? 它们经常发生在系统编程中。 回答1 这就是O_EXCL | O_CREAT open() O_EXCL | O_CREAT标志设计用于: 如果设置了 O_CREAT 和 O_EXCL,如果文件存在,open() 将失败。 检查文件是否存在以及如果文件不存在则创建文件对于执行 open() 的其他线程来说是原子的,该线程在设置了 O_EXCL 和 O_CREAT 的同一目录中命名相同的文件名。 如果设置了 O_EXCL 和 O_CREAT,并且路径命名为符号链接,则 open() 将失败并将 errno 设置为 [EEXIST],无论符号链接的内容如何。 如果设置了 O_EXCL 而未设置 O_CREAT,则结果未定义。 所以: fd = open(FILENAME, O_EXCL | O_CREAT | O_RDWR); if (fd <0) { /* file exists or
  • Stackoverflow热门问题(九)-C确定文件存在的最好方式是什么?
    文章首发及后续更新:https://mwhls.top/2473.html 新的更新内容请到mwhls.top查看。 无图/无目录/格式错误/更多相关请到上方的文章首发页面查看。 stackoverflow热门问题目录 如有翻译问题欢迎评论指出,谢谢。 目录 1. C确定文件存在的最好方式是什么? 2. What’s the best way to check if a file exists in C? C确定文件存在的最好方式是什么? Dave Marshall asked: 有什么比下面更好的途径来尝试打开文件吗?int exists(const char *fname){ FILE *file; if ((file = fopen(fname, “r”))) { fclose(file); return 1; } return 0;}Answers: Graeme Perrow – vote: 670 试试access()函数,头文件是unist.h。用它来将你的函数改为:if( access( fname, F_OK ) == 0 ) { // file exists} else { // file doesn’t exist}使用R_OK, W_OK, X_OK来代替F_OK,可以在确定文件存在的前提上确定文件的读、写、执行权限,并且能够使用 或 来同时使用它们
  • 使用 dup2 时的竞争条件(Race condition when using dup2)
    问题 这个dup2系统调用的联机帮助页说: EBUSY(仅限 Linux) 在与 open(2) 和 dup() 的竞争条件期间,这可能由 dup2() 或 dup3() 返回。 它谈论什么竞争条件,如果dup2 EBUSY错误,我该怎么办? 我应该像EINTR一样重试吗? 回答1 在fs/file.c file.c 中有解释,do_dup2(): /* * We need to detect attempts to do dup2() over allocated but still * not finished descriptor. NB: OpenBSD avoids that at the price of * extra work in their equivalent of fget() - they insert struct * file immediately after grabbing descriptor, mark it larval if * more work (e.g. actual opening) is needed and make sure that * fget() treats larval files as absent. Potentially interesting, * but while extra work in fget(
  • 如果父文件夹不存在,如何写文件?(How to write file if parent folder doesn't exist?)
    问题 我需要将文件写入以下路径: fs.writeFile('/folder1/folder2/file.txt', 'content', function () {…}); 但是'/folder1/folder2'路径可能不存在。 所以我得到以下错误: message = ENOENT,打开/folder1/folder2/file.txt 如何将内容写入该路径? 回答1 首先将mkdirp与path.dirname结合使用。 var mkdirp = require('mkdirp'); var fs = require('fs'); var getDirName = require('path').dirname; function writeFile(path, contents, cb) { mkdirp(getDirName(path), function (err) { if (err) return cb(err); fs.writeFile(path, contents, cb); }); } 如果整个路径已经存在,则mkdirp是noop。 否则,它将为您创建所有丢失的目录。 该模块可以满足您的需求:https://npmjs.org/package/writefile。 在搜寻“ writefile mkdirp”时得到了它。 该模块返回一个promise
  • node.js rmdir 是递归的吗? 它可以在非空目录上工作吗?(Is node.js rmdir recursive ? Will it work on non empty directories?)
    问题 fs.rmdir 的文档非常简短,并且没有解释当目录不为空时 rmdir 的行为。 问:如果我尝试使用此 API 删除非空目录会怎样? 回答1 简短回答: node.js fs.rmdir()调用 POSIX rmdir() ; 这将删除一个空目录,或返回一个错误。 在给定的情况下,调用将调用回调函数并将错误作为异常传递。 这里的问题是 node.js 文档是指 POSIX: Node.js API Docs File System API 最初是 标准 POSIX 函数的简单包装。 这几乎将问题变成了重复:是否有 POSIX API / 函数的列表? fs.rmdir的描述很简洁,但足够了。 异步 rmdir(2)。 此处的rmdir(2)是对 rmdir() 系统调用文档的隐式引用。 此处的数字 (2) 是旧的 unix 手册页约定,表示手册页的第 2 节,其中包含内核接口。 回答2 虽然使用第三方库来做这样的事情,但我想不出更优雅的解决方案。 所以我最终使用了 npm-module rimraf。 安装它 npm install rimraf 或者安装它并保存到“package.json”(其他保存选项可以在 npm-install 文档中找到) npm install --save rimraf 然后您可以执行以下操作: rmdir = require('rimraf
  • 如果使用Node.js不存在目录,如何创建目录?(How to create a directory if it doesn't exist using Node.js?)
    问题 如果目录不存在,这是创建目录的正确方法吗? 它应该对该脚本具有完全的权限,并且可以被其他人读取。 var dir = __dirname + '/upload'; if (!path.existsSync(dir)) { fs.mkdirSync(dir, 0744); } 回答1 var fs = require('fs'); var dir = './tmp'; if (!fs.existsSync(dir)){ fs.mkdirSync(dir); } 回答2 不,出于多种原因。 路径模块不具有exists / existsSync方法。 它在fs模块中。 (也许您只是在输入问题时打错了字?) 该文档明确阻止您使用exists 。 fs.exists()是过时的,仅出于历史原因存在。 几乎永远没有理由在自己的代码中使用它。 特别是,在打开文件之前检查文件是否存在是一种反模式,使您容易受到竞争状况的影响:另一个过程可能会在调用fs.exists()和fs.open()之间删除该文件。 只需打开文件,然后在不存在时处理错误即可。 由于我们在谈论目录而不是文件,因此此建议意味着您应该无条件调用mkdir并忽略EEXIST 。 通常,应避免使用* Sync方法。 它们正在阻塞,这意味着在您访问磁盘时,程序中绝对不会发生任何其他事情。 这是一个非常昂贵的操作
  • 使用 Boost.Asio 执行干净关机的标准方法(standard way to perform a clean shutdown with Boost.Asio)
    问题 我正在使用 Boost.Asio 用 C++ 编写一个跨平台的服务器程序。 按照此页面上的 HTTP 服务器示例,我想在不使用特定于实现的 API 的情况下处理用户终止请求。 我最初尝试使用标准 C 信号库,但一直无法找到适合 Asio 的设计模式。 Windows 示例的设计似乎与信号库最接近,但存在竞争条件,即在服务器对象被销毁后可以调用控制台 ctrl 处理程序。 我试图避免 C++ 标准指定的未定义行为。 是否有标准(且正确)的方法来停止服务器? 为了说明使用 C 信号库的问题: #include <csignal> #include <functional> #include <boost/asio.hpp> using std::signal; using boost::asio::io_service; namespace { std::function<void ()> sighandler; } extern "C" { static void handle_signal(int); } void handle_signal(int) { // error - undefined behavior sighandler(); } int main() { io_service s; sighandler = std::bind(&io_service
  • 当使用锁定文件来避免脚本的两个实例同时运行时,如何避免竞争状况?(How to avoid race condition when using a lock-file to avoid two instances of a script running simultaneously?)
    问题 避免同一脚本的两个实例同时运行的典型方法如下: [ -f ".lock" ] && exit 1 touch .lock # do something rm .lock 有没有更好的方法来锁定shell脚本中的文件,从而避免出现竞争状况? 必须使用目录代替吗? 回答1 是的,示例脚本中确实存在竞争条件。 您可以使用bash的noclobber选项来在比赛中失败,这是因为-f测试和touch之间潜入了另一个脚本。 下面是一个示例代码片段(受本文启发),说明了该机制: if (set -o noclobber; echo "$$" > "$lockfile") 2> /dev/null; then # This will cause the lock-file to be deleted in case of a # premature exit. trap 'rm -f "$lockfile"; exit $?' INT TERM EXIT # Critical Section: Here you'd place the code/commands you want # to be protected (i.e., not run in multiple processes at once). rm -f "$lockfile" trap - INT TERM EXIT
  • 创建新文件,但如果bash中已经存在文件名,则添加数字(Create new file but add number if filename already exists in bash)
    问题 我发现了类似的问题,但在Linux / Bash中却找不到 我希望我的脚本创建一个具有给定名称的文件(通过用户输入),但是如果文件名已经存在,请在末尾添加数字。 例子: $ create somefile Created "somefile.ext" $ create somefile Created "somefile-2.ext" 回答1 以下脚本可以为您提供帮助。 您不应同时运行该脚本的多个副本,以免出现竞争状况。 name=somefile if [[ -e $name.ext || -L $name.ext ]] ; then i=0 while [[ -e $name-$i.ext || -L $name-$i.ext ]] ; do let i++ done name=$name-$i fi touch -- "$name".ext 回答2 更轻松: touch file`ls file* | wc -l`.ext 你会得到: $ ls file* file0.ext file1.ext file2.ext file3.ext file4.ext file5.ext file6.ext 回答3 为了避免比赛条件: name=some-file n= set -o noclobber until file=$name${n:+-$n}.ext { command
  • 这是比赛条件吗?(Is this a race condition?)
    问题 竞赛条件的定义:竞赛条件或竞赛危险是系统或过程中的缺陷,由此过程的输出或结果意外地且严重地取决于其他事件的顺序或时间。 考虑以下伪代码: Global variable i initialized to 6; Thread 1: acquire(lock l) increment global variable i, i.e. i++; Thread 2: acquire(lock l) double the value of global var i, i.e.: i*=2; 如果T1首先获取锁l,然后T2第二,则i的值为14。另一方面,如果T2首先获取锁l,然后T1其次,则i的值为13。 那么,这是否是比赛条件? 更新:经过大量评论和回答后,意见仍存在分歧。 我的意见是“是的,这是一个竞赛条件”类别。 实际上,在另一个问题上,我以竞争状况为例给出了此示例。 同时,我还阅读了“不,这不是比赛条件”类别中的一些有趣评论。 我想我会解决并得出结论,这是一种竞赛条件,还是不是一种竞赛条件,这取决于人们从哪个角度/水平看待问题。 但是,我仍在等待有趣的答案/评论。 回答1 我认为示例算法是否具有竞争条件取决于该算法的预期功能。 i的修改没有数据争用-那些访问被序列化并且彼此之间原子地发生。 但是,如果对算法的正确性很重要的是在乘法运算之前先进行增量运算(反之亦然),那么就存在竞争
  • 如何在 Golang 中使用 Mkdir 创建嵌套目录?(How to create nested directories using Mkdir in Golang?)
    问题 我正在尝试从 Go 可执行文件(例如“dir1/dir2/dir3”)创建一组嵌套目录。 我已经成功地用这一行创建了一个目录: os.Mkdir("." + string(filepath.Separator) + c.Args().First(),0777); 但是,我不知道如何在该目录中创建预定的嵌套目录集。 回答1 os.Mkdir用于创建单个目录。 要创建文件夹路径,请尝试使用: os.MkdirAll(folderPath, os.ModePerm) Go 文档 func MkdirAll(path string, perm FileMode) 错误 MkdirAll 创建一个名为 path 的目录以及任何必要的父目录,并返回 nil,否则返回错误。 权限位 perm 用于 MkdirAll 创建的所有目录。 如果 path 已经是一个目录,则 MkdirAll 什么都不做并返回 nil。 编辑: 更新为正确使用os.ModePerm代替。 对于文件路径的串联,请使用@Chris 的回答中所述的包path/filepath文件路径。 回答2 这样您就不必使用任何幻数: os.MkdirAll(newPath, os.ModePerm) 此外,您可以使用: import "path/filepath" path := filepath.Join
  • 自动创建带有文件输出的目录(Automatically creating directories with file output [duplicate])
    问题 这个问题已经在这里有了答案: 8年前关闭。 可能重复: python中的mkdir -p功能 假设我要制作文件: filename = "/foo/bar/baz.txt" with open(filename, "w") as f: f.write("FOOBAR") 由于/foo/bar不存在,因此将产生IOError 。 自动生成这些目录的最Python方式是什么? 对我来说,是否有必要在每一个os.mkdir上分别显式地调用os.path.exists和os.mkdir (即,/ foo,然后是/ foo / bar)? 回答1 os.makedirs函数执行此操作。 请尝试以下方法: import os import errno filename = "/foo/bar/baz.txt" if not os.path.exists(os.path.dirname(filename)): try: os.makedirs(os.path.dirname(filename)) except OSError as exc: # Guard against race condition if exc.errno != errno.EEXIST: raise with open(filename, "w") as f: f.write("FOOBAR") 添加try
  • Node.js创建文件夹或使用现有文件夹(Node.js create folder or use existing)
    问题 我已经阅读了Node.js的文档,除非我错过了一些内容,否则它不会告诉某些操作(尤其是fs.mkdir())中包含哪些参数。 正如您在文档中看到的那样,它不是很多。 当前,我有以下代码,该代码尝试创建一个文件夹或使用现有的文件夹: fs.mkdir(path,function(e){ if(!e || (e && e.code === 'EEXIST')){ //do something with contents } else { //debug console.log(e); } }); 但是我想知道这是正确的方法吗? 检查代码EEXIST是否正确知道文件夹已存在? 我知道我可以在创建目录之前执行fs.stat() ,但这已经是对文件系统的两次打击。 其次,是否有Node.js的完整或至少是更详细的文档,其中包含有关错误对象包含的内容,参数表示的内容等的详细信息。 回答1 做到这一点的好方法是使用mkdirp模块。 $ npm install mkdirp 使用它来运行需要目录的功能。 创建路径后或路径已经存在时将调用回调。 如果mkdirp创建目录路径失败,则会设置错误err 。 var mkdirp = require('mkdirp'); mkdirp('/tmp/some/path/foo', function(err) { // path exists