title: What can cause close(2) to fail with EIO for a read-only file?
body: <p>I'm investigating a problem on Android where an <code>IOException</code> is getting thrown because of a failure to close a file:</p>
  
  <pre><code>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></pre>
  
  <p>The relevant code:</p>
  
  <pre><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();
      }
  }
  </code></pre>
  
  <p>The full source is <a href="https://github.com/adamantoise/wordswithcrosses/blob/master/wordswithcrosses/src/com/adamrosenfield/wordswithcrosses/io/JPZIO.java" rel="nofollow">on GitHub</a>.</p>
  
  <p>The exception is being thrown from the line <code>fis.close()</code>.  From what I can tell from reading the Android sources, it looks like <code>FileInputStream.close()</code> just calls down into <a href="http://linux.die.net/man/2/close" rel="nofollow"><code>close(2)</code></a> on the underlying file descriptor in native code.</p>
  
  <p>The manual pages don't seem to specify what can cause an <code>EIO</code> 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.</p>
  
  <p>What exactly can cause <code>close(2)</code> to fail with the error <code>EIO</code> for a file descriptor which was only opened for reading, as in this case?  Clearly it's not an uncommitted <code>write(2)</code>.  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 (<a href="https://github.com/adamantoise/wordswithcrosses/blob/master/wordswithcrosses/src/com/adamrosenfield/wordswithcrosses/net/AbstractJPZDownloader.java#L58" rel="nofollow">here</a>), but unless Android has an undocumented time machine in it, future code ought not to have an affect here.</p>
  
  <p>I'm interested specifically in the answer on Android and/or Linux, but a more general answer for other OSes would also be appreciated.</p>