什么会导致接近(2)不能与EIO为只读文件? [英] What can cause close(2) to fail with EIO for a read-only file?

查看:1453
本文介绍了什么会导致接近(2)不能与EIO为只读文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我调查Android上的一个问题,即一个 IOException异常由于未能关闭文件的是越来越抛出:

I'm investigating a problem on Android where an IOException is getting thrown because of a failure to close a file:

java.io.IOException: close failed: EIO (I/O error)
    at libcore.io.IoUtils.close(IoUtils.java:41)
    at java.io.FileInputStream.close(FileInputStream.java:121)
    at com.adamrosenfield.wordswithcrosses.io.JPZIO.convertJPZPuzzle(JPZIO.java:191)
    at com.adamrosenfield.wordswithcrosses.net.AbstractJPZDownloader.download(AbstractJPZDownloader.java:56)
    at com.adamrosenfield.wordswithcrosses.net.AbstractJPZDownloader.download(AbstractJPZDownloader.java:41)
    at com.adamrosenfield.wordswithcrosses.net.AbstractDownloader.download(AbstractDownloader.java:112)
    at com.adamrosenfield.wordswithcrosses.net.AbstractDownloader.download(AbstractDownloader.java:108)
    at com.adamrosenfield.wordswithcrosses.net.Downloaders.download(Downloaders.java:257)
    at com.adamrosenfield.wordswithcrosses.BrowseActivity.internalDownload(BrowseActivity.java:702)
    at com.adamrosenfield.wordswithcrosses.BrowseActivity.access$6(BrowseActivity.java:696)
    at com.adamrosenfield.wordswithcrosses.BrowseActivity$7.run(BrowseActivity.java:691)
    at java.lang.Thread.run(Thread.java:856)
Caused by: libcore.io.ErrnoException: close failed: EIO (I/O error)
    at libcore.io.Posix.close(Native Method)
    at libcore.io.BlockGuardOs.close(BlockGuardOs.java:75)
    at libcore.io.IoUtils.close(IoUtils.java:38)
    ... 11 more

相关code:

public static void convertJPZPuzzle(File jpzFile, File destFile,
        PuzzleMetadataSetter metadataSetter) throws IOException {
    FileInputStream fis = new FileInputStream(jpzFile);
    try {
        DataOutputStream dos = new DataOutputStream(new FileOutputStream(destFile));
        try {
            if (!convertJPZPuzzle(fis, dos, metadataSetter)) {
                throw new IOException("Failed to convert JPZ file: " + jpzFile);
            }
        } finally {
            dos.close();
        }
    } finally {
        fis.close();
    }
}

完整的源代码是<一个href=\"https://github.com/adamantoise/wordswithcrosses/blob/master/wordswithcrosses/src/com/adamrosenfield/wordswithcrosses/io/JPZIO.java\"相对=nofollow>在GitHub上。

唯一的例外是从该行抛出 fis.close()。从我可以从阅读Android的消息来源告诉,它看起来像 FileInputStream.close()只是调用成的 关闭(2) 在本地code底层的文件描述符。

The exception is being thrown from the line fis.close(). From what I can tell from reading the Android sources, it looks like FileInputStream.close() just calls down into close(2) on the underlying file descriptor in native code.

手册页似乎并没有规定什么能引起 EIO 的错误,他们只是说这样的话发生I / O错误。或者如果在读取或写入时对文件系统的密切发生I / O错误()。 Mac OS X的手册页说,则可能出现A previously,未提交的写(2)遇到输入/输出错误。在这些系统上。

The manual pages don't seem to specify what can cause an EIO error, they just say things like "An I/O error occurred." or "If an I/O error occurred while reading from or writing to the file system during close()". The Mac OS X man pages say it can occur when "A previously-uncommitted write(2) encountered an input/output error." on those systems.

究竟能引起关闭(2)失败,出现错误 EIO 为这只是一个文件描述符打开阅读,因为在这种情况下?显然,这不是一个未提交写(2)。在这个特定的文件的情况下,使用Android的下载管理服务,这意味着有可能是挥之不去的线程和/或试图同时访问它的进程被下载,但我几乎看不到如何会影响试图将其关闭。此外,该文件只是这个code运行之后被删除(<一个href=\"https://github.com/adamantoise/wordswithcrosses/blob/master/wordswithcrosses/src/com/adamrosenfield/wordswithcrosses/net/AbstractJPZDownloader.java#L58\"相对=nofollow>这里),但除非Android有一个未公开的时间机器在里面,未来的code不应该有一个影响在这里。

What exactly can cause close(2) to fail with the error EIO for a file descriptor which was only opened for reading, as in this case? Clearly it's not an uncommitted write(2). In the case of this particular file, it was downloaded using Android's DownloadManager service, which means there might be lingering threads and/or processes trying to access it simultaneously, but I can hardly see how that would affect trying to close it. Also, the file is just about to be deleted after this code runs (here), but unless Android has an undocumented time machine in it, future code ought not to have an affect here.

我在Android和/或Linux的回答特别感兴趣,但对其他操作系统更普遍的答案也将是AP preciated。

I'm interested specifically in the answer on Android and/or Linux, but a more general answer for other OSes would also be appreciated.

推荐答案

我猜 EIO 来自 bad_file_flush FS / bad_inode.c 。看来当内核出现任何故障访问一个inode,它把打开的文​​件描述的伪开文件, bad_inode_ops 作为其文件的欢声笑语。我找不到code,这是否为基于FAT的文件系统,但也许有一些通用的code。

I'm guessing the EIO comes from bad_file_flush in fs/bad_inode.c. It seems when the kernel has any failure accessing an inode, it transforms the open file description to a pseudo-open-file of with bad_inode_ops as its file ops. I can't find the code that does this for FAT-based filesystems, but perhaps there's some generic code.

至于原因,它可能像从相连的计算机连接USB电缆和安装文件系统,取出SD卡等。

As for the reason, it's probably something like attaching a USB cable and mounting the filesystem from an attached computer, removing the SD card, etc.

这篇关于什么会导致接近(2)不能与EIO为只读文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆