Re: 答复: (fc) FileChannel.transferFrom/transferFromArbitraryChannel to return -1 at some error condition

Alan Bateman Alan.Bateman at oracle.com
Fri Jan 29 17:07:13 UTC 2021


On 29/01/2021 12:51, lihuaming (A) wrote:
>
> Here is a simple demo, I don't use FileChannel.transferFrom directly, 
> but I hope I can clarify the situation.
>
> When ServerHangHttp and Client are up for a while (please check the 
> bottom), no matter Server close the socket explicitly or kill by "kill 
> -9 xxx", the client side will print out "[client] read : -1" 
> continuously. so, if we are using FileChannel.transferFrom which will 
> call transferFromArbitraryChannel which will call 
> ReadableByteChannel.read, ReadableByteChannel.read will return -1, but 
> transferFromArbitraryChannel will return 0, so as 
> FileChannel.transferFrom. Based on this return value, following while 
> loop will be a infinite loop, and user don't want to call something 
> like "call sth like srcSocketChannel.read(...)", please check the 
> reason in comments below.
>
> while (srcSocketChannel.isOpen()) {
>
>   long l = fileChannel.transferFrom(srcSocketChannel,...);
>   // user could call sth like srcSocketChannel.read(...), and expect 
> it return -1, and break the loop, but it will be unacceptable for some 
> program, where they would like to very quick copy, so called "zero" 
> copy through fileChannel.transferFrom, and they don't want to add an 
> extra check like "srcSocketChannel.read(...)"
>   if (l == -1) { // break out the while loop }
>
> }
>
> At this situation, I think it's more friendly to have 
> fileChannel.transferFrom returns -1.
>
The Client in the reproducer has a bug in that it will call read with 0 
remaining bytes once it has read 100 bytes in total. So I would expect 
it will eventually spin reading 0 rather than -1. If the server does 
terminate and close the connection gracefully then the client will spin 
reading -1 but only if reads -1/EOF before 1000 bytes are read. For 
transferFrom reading from an arbitrary channel then it may read bytes 
before EOF, in which case it will write those bytes to the file and 
return the number of bytes written/transferred. If called again then it 
will read again and just 0 because there are no bytes transferred. I 
don't see how we can could change this API without breaking existing 
usages that keeping a running code.

-Alan
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.java.net/pipermail/nio-dev/attachments/20210129/357177d0/attachment-0001.htm>


More information about the nio-dev mailing list