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.