JDK-6427312 : (fc) FileChannel.transferTo() throws IOException "system call interrupted"
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.nio
  • Affected Version: 5.0
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: linux
  • CPU: x86
  • Submitted: 2006-05-18
  • Updated: 2019-03-15
  • Resolved: 2011-05-18
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6 JDK 7
6u18Fixed 7 b05Fixed
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.5.0_04"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_04-b05)
Java HotSpot(TM) Client VM (build 1.5.0_04-b05, mixed mode, sharing)


ADDITIONAL OS VERSION INFORMATION :
Linux c001n01 2.6.5-SLES9-SP2-62670d15449ecdfe8084f3f4aa6e38ac #1 SMP Thu Mar 16 09:28:14 EST 2006 i686 i686 i386 GNU/Linux

A DESCRIPTION OF THE PROBLEM :
On Linux, FileChannel.transferTo() occasionally throws a "java.io.IOException: Interrupted system call".

The reason seems to be that the linux implementation of sun.nio.ch.FileChannelImpl.transferTo0() does not handle -EINTR return values from the sendfile() system call correctly.

Proposed solution: when sendfile() returns a negative value, check whether offset was incremented. If it was, return the delta (i.e.: the nr of bytes transferred) instead of throwing an exception. This allows the client to resume the transfer from the new position.

The Solaris implementation handles this case correctly.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Repeatedly transfer a large file (100MB or larger) to a blocking NIO socket using FileChannel.transferTo(). Eventually, the sendfile() system call will be interrupted and an IOException will be thrown.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
When interrupted, sun.nio.ch.FileChannelImpl.transferTo0() should return the actual nr of bytes transferred (can be 0) instead of throwing an IOException.

Throwing the exception leaves no option to recover since information about the nr of bytes already transferred is lost.

ACTUAL -
FileChannel.transferTo() threw the exception below.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
java.io.IOException: Interrupted system call
        at sun.nio.ch.FileChannelImpl.transferTo0(Native Method)
        at sun.nio.ch.FileChannelImpl.transferToDirectly(Unknown Source)
        at sun.nio.ch.FileChannelImpl.transferTo(Unknown Source)
        at com.emc.centera.library.io.transfer.TransferChannelAdaptor.doTransfer(TransferChannelAdaptor.java:94)


REPRODUCIBILITY :
This bug can be reproduced often.

CUSTOMER SUBMITTED WORKAROUND :
The only workaround is to replace FileChannel.transferTo() calls by code that does explicit FileChannel.read() and SocketChannel.write() calls.

This results in a significant performance degradation.

Comments
EVALUATION Yes, we need to fix this. The original man pages for sendfile(2) didn't document EINTR but the updated pages suggest it can only be interrupted before any data is transmitted - we need to verify this and if true, retry the sendfile as we do with other interrupted calls.
18-05-2006