我的应用程序使用lseek()查找所需的位置来写入数据。使用open()成功打开了该文件,并且我的应用程序能够多次使用lseek()和write()。
在给定的时间,对于一些不易重现的用户,lseek()返回-1,errno为9。在此之前,文件不会关闭,文件句柄(整型)也不会重置。
在此之后,将创建另一个文件;open()再次正常工作,lseek()和write()再次工作。
更糟糕的是,这个用户再次尝试了完整的序列,一切都很好。
所以我的问题是,由于某些原因,操作系统可以为我关闭文件句柄吗?是什么导致了这种情况?文件索引器或某种文件扫描器?
解决这个问题的最好方法是什么?伪代码是最好的解决方案吗?(别管代码布局,我会为它创建函数)
int fd=open(...);
if (fd>-1) {
long result = lseek(fd,....);
if (result == -1 && errno==9) {
close(fd..); //make sure we try to close nicely
fd=open(...);
result = lseek(fd,....);
}
}有谁有过类似的经历吗?
摘要:对于给定的fd,文件寻道和写入工作正常,并且突然无缘无故地返回errno=9。
发布于 2010-03-30 20:47:37
我不知道你有什么类型的设置,但是下面的场景,我认为可以产生这样的效果(或者类似的效果)。我没有对此进行验证,所以请对此持保留态度。
如果您要打开的文件/设备实现为服务器应用程序(例如NFS),请考虑如果服务器应用程序宕机/重新启动/重新启动会发生什么情况。尽管文件描述符最初在客户端有效,但可能不再映射到服务器端的有效文件句柄。可以想象,这会导致一系列事件,其中客户端将获得EBADF。
希望这能有所帮助。
发布于 2010-03-30 20:46:28
所以我的问题是,由于某些原因,操作系统可以为我关闭文件句柄吗?是什么导致了这一点?文件索引器或某种文件扫描器?
不,这不会发生。
解决这个问题的最好方法是什么;伪代码是最好的解决方案吗?(别管代码布局,我会为它创建函数)
不,最好的方法是找到bug并修复它。
有没有人有过类似的经历?
我见过很多次fds搞得一团糟,在某些情况下导致EBADF,在另一些情况下发生了惊人的爆炸,它是:
if(fd == foo[i].fd)if(fd = foo[i].fd)操作,而某些线程关闭了其他线程想要使用的错误文件描述符。如果你能找到重现这个问题的方法,在“strace”下运行你的程序,这样你就能看到发生了什么。
发布于 2010-03-30 20:13:35
操作系统不应该随意关闭文件句柄(我假设是类Unix系统)。如果你的文件句柄被关闭了,那么你的代码就有问题,很可能是在其他地方(多亏了C语言和Unix API,这可以在代码中的任何地方出现,并且可能是由于,例如,在看起来确实不相关的某段代码中有轻微的缓冲区溢出)。
你的伪代码是最糟糕的解决方案,因为它会给你一种已经修复了问题的印象,而bug仍然潜伏着。
我建议您在打开和关闭文件或套接字的任何地方添加调试打印(即printf()调用)。另外,也可以试试Valgrind。
(我昨天刚刚遇到了一个可怕的off- by -1缓冲区溢出,它损坏了编译器为保存CPU寄存器而生成的临时槽的最低有效字节;其间接影响是另一个函数中的结构似乎移位了几个字节。我花了相当多的时间来理解发生了什么,包括一些彻底阅读Mips汇编代码)。
https://stackoverflow.com/questions/2544898
复制相似问题