JDK 9 RFR of 8175209: Account for race condition in java/nio/channels/AsynchronousSocketChannel/Basic.java

Hamlin Li huaming.li at oracle.com
Fri Mar 3 05:45:56 UTC 2017

Hi Brian,

I believe the patch will improve the stability of the test than original 

But I'm afraid the patch will still face the intermittent failure, 
because there is still a time window for ch.write(genBuffer()); to run 
successfully, then exception is thrown at line 357.

  356                 ch.write(genBuffer());
  357                 throw new RuntimeException("WritePendingException expected");

It can be reproduced by putting below code in a loop as below, and reduce the sleep time to 10, my local test result is to fail at about one hundred or hundreds of loops.

for (int i = 0; i < 1000; i++) { // put below code in a loop

  323             ch = AsynchronousSocketChannel.open();
  324             ch.connect(server.address()).get();
345 int prevNumCompleted = numCompleted.get();
346 do {
347 Thread.sleep(*10*);
348 if (numCompleted.get() == prevNumCompleted) {
349 break;
350 }
351 prevNumCompleted = numCompleted.get();
352 } while (true);
  369             if (!(writeException.get() instanceof AsynchronousCloseException))
  370                 throw new RuntimeException("AsynchronousCloseException expected",
  371                         writeException.get());

} // end of for loop

The reason why it fails is because there are 2 writes,
   write_1) one is at line 331 and line 334, they continuously write to 
buffer, the writes are expected to run successfully except of the time 
when ch is closed.
   write_2) another is at line 356, it writes just once, and expected to 
fail with WritePendingException
write_1 and write_2 are racy, any time wait or sync would not change the 
racy relationship, so the intermittent failure is expected ( based on 
original code or your patch).


  331             ch.write(genBuffer(), ch, new CompletionHandler<Integer,AsynchronousSocketChannel>() {
  332                 public void completed(Integer result, AsynchronousSocketChannel ch) {
333 numCompleted.incrementAndGet();
  334                     ch.write(genBuffer(), ch, this);
  335                 }


  355             try {
  356                 ch.write(genBuffer());
  357                 throw new RuntimeException("WritePendingException expected");
  358             } catch (WritePendingException x) {

I think we can use the racy relationship between write_1 and write_2 
rather than try to avoid it,
How do you think about below solution?
   make write_2 to write continuously to the channel too. As write_1 and 
write_2 are racy, WritePendingException is expected to happen either in 
write_1 or write_2. If either write_1 or write_2 throw 
WritePendingException, the test is passed; if no exception is thrown(in 
a reasonable time span or in infinite time?), then the test fails.

Thank you

On 2017/3/1 5:15, Brian Burkhalter wrote:
> Improved version which counts the number of invocations of 
> CompletionHandler.completed() instead of tracking the time of the most 
> recent invocation:
> http://cr.openjdk.java.net/~bpb/8175209/webrev.01/ 
> <http://cr.openjdk.java.net/%7Ebpb/8175209/webrev.01/>
> Also delete unused variable t0.
> Thanks,
> Brian
> On Feb 28, 2017, at 8:25 AM, Brian Burkhalter 
> <brian.burkhalter at oracle.com <mailto:brian.burkhalter at oracle.com>> wrote:
>> Please review this test bug fix at your convenience.
>> Issue:https://bugs.openjdk.java.net/browse/JDK-8175209
>> Patch:http://cr.openjdk.java.net/~bpb/8175209/webrev.00/ 
>> <http://cr.openjdk.java.net/%7Ebpb/8175209/webrev.00/>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/nio-dev/attachments/20170303/88303fc6/attachment-0001.html>

More information about the nio-dev mailing list