const std::string propName(pPropName, len);
std::filesystem::path p(pPropName);
if (!std::filesystem::exists(p)) {
LOG( Log::Level::ERROR,
"File %s does not exist w/len = %u",
propName.c_str(),
len);
return;
}
出于某种原因,在一个卷中发生过几次std::filesystem::exists(p)
返回false
(在我修改了现有文件并用vi
保存之后(,而该文件确实存在——我立即对该文件进行了ls
处理。
boost::filesystem::exists()
中有一个非常相似的帖子报告了类似的问题。
一个答案建议vi
在保存文件之前创建一个临时文件(即:w
(。然而,上面的代码是在我在vi
中点击:wq!
几秒钟后手动触发的。我甚至在1分钟2分钟后又试了2次。CCD_ 10仍然返回CCD_。
另一个答案表明,这可能是一个许可问题。然而,我的情况并非如此,因为11分钟后,相同的代码和相同的二进制文件看到了文件(即std::filesystem::exists()
返回true
(,我甚至没有重新启动我的进程(包含上面的代码(。
困难的是,它不是100%可复制的——我刚刚编辑了上面的代码,以传入std::error_code
的一个实例,试图获得错误代码。但我现在无法复制。
知道吗?
我使用g++
8.3.1进行编译,代码运行在CentOS 7.7上。
=====
更新#1:文件大小约为5190字节,它位于3+GHz Intel服务器上的SSD上。
更新#2:这是strace
的输出(当std::filesystem::exists(p)
返回true时捕获(:
stat("/server/my_file.ini", {st_mode=S_IFREG|0775, st_size=5077, ...}) = 0
open("/server/my_file.ini", O_RDONLY) = 15
更新#3:发现问题——pPropName
有时可能不是null终止的(应该使用propName
(。并且CCD_ 20返回"0";成功";,奇怪的不管怎样,谢谢大家。
在创建新文件之前,实际上是vi
重命名了目标文件(这让我很惊讶(。
我通过在编辑一个文件(the_file
(时运行这个程序来验证它。
#include <filesystem>
#include <iostream>
int main() {
std::filesystem::path p("the_file");
while(std::filesystem::exists(p));
std::cout << "gonen";
}
当在vi
中执行:wq
时,程序打印gone
并退出。
另外,vi
会话的strace
对其进行验证。这是在返回命令:wq
后的strace -ff
日志。注意rename
、openat
序列:
read(0, "r", 250) = 1
select(1, [0], [], [0], {tv_sec=0, tv_usec=0}) = 0 (Timeout)
write(1, "r", 1) = 1
stat("/home/ted/proj/stackoverflow/the_file", {st_mode=S_IFREG|0644, st_size=7, ...}) = 0
access("/home/ted/proj/stackoverflow/the_file", W_OK) = 0
write(1, "33[?25l33[?2004l33[>4;m", 20) = 20
ioctl(0, SNDCTL_TMR_START or TCSETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(0, TCGETS, {B38400 opost isig icanon echo ...}) = 0
write(1, ""the_file"", 10) = 10
stat("the_file", {st_mode=S_IFREG|0644, st_size=7, ...}) = 0
access("the_file", W_OK) = 0
getxattr("the_file", "system.posix_acl_access", 0x7fffb80a2f50, 132) = -1 ENODATA (No data available)
stat("the_file", {st_mode=S_IFREG|0644, st_size=7, ...}) = 0
lstat("the_file", {st_mode=S_IFREG|0644, st_size=7, ...}) = 0
lstat("4913", 0x7fffb80a32e0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "4913", O_WRONLY|O_CREAT|O_EXCL|O_NOFOLLOW, 0100644) = 3
fchown(3, 1000, 100) = 0
stat("4913", {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
close(3) = 0
unlink("4913") = 0
stat("the_file~", 0x7fffb80a3000) = -1 ENOENT (No such file or directory)
stat("the_file", {st_mode=S_IFREG|0644, st_size=7, ...}) = 0
stat("the_file~", 0x7fffb80a1fd0) = -1 ENOENT (No such file or directory)
unlink("the_file~") = -1 ENOENT (No such file or directory)
rename("the_file", "the_file~") = 0
openat(AT_FDCWD, "the_file", O_WRONLY|O_CREAT, 0644) = 3
ftruncate(3, 0) = 0
write(3, "hejsann", 7) = 7
fsync(3) = 0
stat("the_file", {st_mode=S_IFREG|0644, st_size=7, ...}) = 0
stat("the_file", {st_mode=S_IFREG|0644, st_size=7, ...}) = 0
fchmod(3, 0100644) = 0
close(3) = 0
setxattr("the_file", "system.posix_acl_access", "2 1 6 3773773773774 4 377377377377 4 377377377377", 28, 0) = 0
write(1, " 1L, 7C written", 15) = 15
stat("/home/ted/proj/stackoverflow/the_file", {st_mode=S_IFREG|0644, st_size=7, ...}) = 0
unlink("the_file~") = 0
write(1, "rrn33[?2004l33[?1l33>", 18) = 18
write(1, "33[?25h33[>4;m33[?1049l33[23;0;0t", 29) = 29
close(4) = 0
unlink("/home/ted/proj/stackoverflow/.the_file.swp") = 0
exit_group(0) = ?
+++ exited with 0 +++
一种更简单的验证方法是在使用vi
之前和之后检查文件的inode
编号。打开一个文件并执行:wq
将创建一个新文件,其中包含一个新的inode
编号。
但这并不能解释为什么文件在很长一段时间后都不可见。这可能是因为某个地方有一些藏匿处。显然,XFS文件系统有(或曾经(一些问题,因为它的缓存没有为小文件正确更新。如果exists(p) == false
:,也许您可以添加此项
system("sync;sync;sync"); // old classic tripple sync
以将缓存的写入同步到永久存储。之后,请再次尝试检查。