lseek / write突然返回-1,errno = 9(错误的文件描述符)

我的应用程序使用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。

我不知道你有什么类型的设置,但是下面的场景,我认为会产生这样的效果(或者类似于它)。 我没有对此进行测试以validation,所以请带上一粒盐。

如果要打开的文件/设备实现为服务器应用程序(例如NFS),请考虑如果服务器应用程序关闭/重新启动/重新启动会发生什么。 尽管最初在客户端有效的文件描述符可能不再映射到服务器端的有效文件句柄。 这可以想象地导致一系列事件,其中客户端将获得EBADF。

希望这可以帮助。

所以我的问题是,操作系统可以出于某种原因为我关闭文件句柄吗? 什么可能导致>这个? 某种文件索引器或文件扫描程序?

不,这不会发生。

解决这个问题的最佳方法是什么? 这个伪代码是最好的解决方案吗? (别介意代码布局,会为它创建函数)

不,最好的方法是找到错误并修复它。

有人遇到过类似的经历吗?

我已经看到fds多次搞砸了,在某些情况下导致了EBADF,而在其他情况下爆炸性地爆发了,它一直是:

  • 缓冲区溢出 – 溢出的东西,并将一个无意义的值写入’int fd;’ 变量。
  • 发生愚蠢的错误,因为某些角落的情况有人做了if(fd = foo[i].fd)当他们的意思if(fd == foo[i].fd)
  • 线程之间的竞争条件,某些线程关闭了其他线程想要使用的错误文件描述符。

如果您能找到重现此问题的方法,请在“strace”下运行您的程序,以便了解最新情况。

操作系统不应随机关闭文件句柄(我假设是类Unix系统)。 如果您的文件句柄已关闭,那么您的代码有问题,很可能是其他地方(感谢C语言和Unix API,这可能是代码中的任何地方,并且可能是由于,例如,轻微的缓冲溢出一段代码,看起来真的是无关的)。

你的伪代码是最糟糕的解决方案,因为它会给你一个解决问题的印象,而bug仍然潜伏着。

我建议你在打开和关闭文件或套接字的地方添加调试打印(即printf()调用)。 另外,试试Valgrind 。

(我昨天刚刚有一个怪异的1个缓冲区溢出,它损坏了编译器生成的临时槽的最低有效字节以保存CPU寄存器;间接影响是另一个函数中的结构似乎被移位了几个字节。我花了很长时间才了解发生了什么,包括对Mips汇编代码的全面阅读。

不,操作系统不应该像这样关闭文件句柄,而其他应用程序(文件扫描程序等)也不应该这样做。

不要解决问题,找到它的来源。 如果您不知道问题的原因是什么,您永远不会知道您的解决方法是否确实有效。

  1. 检查你的假设。 呼叫前errno是否设置为0? fd在拨打电话时真的有效吗? (我知道你说的是,但是你检查了吗?)
  2. puts( strerror( 9 ) );的输出是什么puts( strerror( 9 ) ); 在你的平台上?