我的应用程序使用lseek()
来寻找所需的位置来写入数据。使用open()
成功打开了文件,并且我的应用程序能够多次使用lseek()
和write()
。
在给定的时间,对于某些用户并且不容易重现,lseek()
返回-1,errno
为9。在此之前文件未关闭,并且文件句柄(int)未重置。
在此之后,创建另一个文件;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。
5条答案
按热度按时间cuxqih211#
所以我的问题是,操作系统能因为某种原因为我关闭文件句柄吗?是什么原因导致的?是文件索引器还是某种文件扫描器?
不,这不会发生。
什么是最好的解决办法;这个伪代码是最好的解决方案吗?(不要介意代码布局,将为它创建函数)
不,最好的方法是找到bug并修复它。
有人有过类似的经历吗?
我见过很多次fds被搞砸了,在某些情况下导致了EBADF,在其他情况下则发生了惊人的爆炸,它是:
if(fd = foo[i].fd)
,而他们的意思是if(fd == foo[i].fd)
如果你能找到重现这个问题的方法,在'strace'下运行你的程序,这样你就能看到发生了什么。
iszxjhcz2#
操作系统不应该随机关闭文件句柄(我假设是一个类Unix系统)。如果你的文件句柄被关闭了,那么你的代码中有一些错误,很可能是在其他地方(由于C语言和Unix API,这可以在代码中的任何地方,可能是由于,例如,在一些看起来不相关的代码中有轻微的缓冲区溢出)。
你的伪代码是最糟糕的解决方案,因为它会给予你一种已经解决了问题的印象,而bug仍然潜伏着。
我建议你在打开和关闭文件或套接字的任何地方添加调试打印(即
printf()
调用)。(我昨天刚刚遇到一个怪异的off-by-1缓冲区溢出,它损坏了编译器为保存CPU寄存器而生成的临时槽的最低有效字节;间接的影响是,另一个函数中的一个结构似乎被移位了几个字节。我花了相当长的时间才明白是怎么回事,包括一些对Mips汇编代码的透彻阅读)。
jucafojl3#
我不知道你有什么类型的设置,但下面的情况下,我认为可以产生这样的效果(或类似的).我还没有测试这一点来验证,所以请采取它与一粒盐.
如果您打开的文件/设备是作为服务器应用程序实现的(例如NFS),请考虑如果服务器应用程序关闭/重新启动/重新启动会发生什么。文件描述符虽然在客户端最初有效,但可能不再Map到服务器端的有效文件句柄。这可能会导致一系列事件,其中客户端将获得EBADF。
希望这能帮上忙。
kxe2p93d4#
不,操作系统不应该像那样关闭文件句柄,其他应用程序(文件扫描仪等)不应该 * 能够 * 这样做。
如果你不知道你的问题的原因是什么,你将永远不会知道你的解决方法是否真的有效。
1.检查你的假设。在调用之前
errno
是否设置为0?fd在进行调用时是否真的有效?(我知道你说它是有效的,但你检查了吗?)puts( strerror( 9 ) );
在您的平台上的输出是什么?g6ll5ycj5#
我有非常类似的错误,但根本原因是完全不同的。根据link,
EBADF
可能会出现,例如当“描述符上的I/O [...]已关闭[...]”时。我将所有内容封装在一个漂亮的类中,它确实在移动时关闭了描述符。请查看代码的固定片段,这样你就会知道原因: