Skip to content

Commit ea73e05

Browse files
author
Brian Burkhalter
committed
8345181: (ch) Windows asynchronous channels may return temporary direct buffers to the buffer cache twice (win)
Reviewed-by: alanb, michaelm
1 parent ee0f88c commit ea73e05

File tree

2 files changed

+34
-10
lines changed

2 files changed

+34
-10
lines changed

src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java

+13-2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525

2626
package sun.nio.ch;
2727

28+
import java.lang.invoke.MethodHandles;
29+
import java.lang.invoke.VarHandle;
2830
import java.nio.channels.*;
2931
import java.util.concurrent.*;
3032
import java.nio.ByteBuffer;
@@ -34,6 +36,7 @@
3436
import jdk.internal.access.SharedSecrets;
3537
import jdk.internal.access.JavaIOFileDescriptorAccess;
3638
import jdk.internal.event.FileForceEvent;
39+
import jdk.internal.invoke.MhUtil;
3740

3841
/**
3942
* Windows implementation of AsynchronousFileChannel using overlapped I/O.
@@ -383,10 +386,13 @@ protected void implRelease(FileLockImpl fli) throws IOException {
383386
* Task that initiates read operation and handles completion result.
384387
*/
385388
private class ReadTask<A> implements Runnable, Iocp.ResultHandler {
389+
private static final VarHandle RELEASED = MhUtil.findVarHandle(MethodHandles.lookup(),
390+
"released", boolean.class);
386391
private final ByteBuffer dst;
387392
private final int pos, rem; // buffer position/remaining
388393
private final long position; // file position
389394
private final PendingFuture<Integer,A> result;
395+
private volatile boolean released;
390396

391397
// set to dst if direct; otherwise set to substituted direct buffer
392398
private volatile ByteBuffer buf;
@@ -405,8 +411,9 @@ private class ReadTask<A> implements Runnable, Iocp.ResultHandler {
405411
}
406412

407413
void releaseBufferIfSubstituted() {
408-
if (buf != dst)
414+
if (buf != dst && RELEASED.compareAndSet(this, false, true)) {
409415
Util.releaseTemporaryDirectBuffer(buf);
416+
}
410417
}
411418

412419
void updatePosition(int bytesTransferred) {
@@ -569,10 +576,13 @@ <A> Future<Integer> implRead(ByteBuffer dst,
569576
* Task that initiates write operation and handles completion result.
570577
*/
571578
private class WriteTask<A> implements Runnable, Iocp.ResultHandler {
579+
private static final VarHandle RELEASED = MhUtil.findVarHandle(MethodHandles.lookup(),
580+
"released", boolean.class);
572581
private final ByteBuffer src;
573582
private final int pos, rem; // buffer position/remaining
574583
private final long position; // file position
575584
private final PendingFuture<Integer,A> result;
585+
private volatile boolean released;
576586

577587
// set to src if direct; otherwise set to substituted direct buffer
578588
private volatile ByteBuffer buf;
@@ -591,8 +601,9 @@ private class WriteTask<A> implements Runnable, Iocp.ResultHandler {
591601
}
592602

593603
void releaseBufferIfSubstituted() {
594-
if (buf != src)
604+
if (buf != src && RELEASED.compareAndSet(this, false, true)) {
595605
Util.releaseTemporaryDirectBuffer(buf);
606+
}
596607
}
597608

598609
void updatePosition(int bytesTransferred) {

src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java

+21-8
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,15 @@
2525

2626
package sun.nio.ch;
2727

28+
import java.lang.invoke.MethodHandles;
29+
import java.lang.invoke.VarHandle;
2830
import java.nio.channels.*;
2931
import java.nio.ByteBuffer;
3032
import java.nio.BufferOverflowException;
3133
import java.net.*;
3234
import java.util.concurrent.*;
3335
import java.io.IOException;
36+
import jdk.internal.invoke.MhUtil;
3437
import jdk.internal.misc.Unsafe;
3538
import sun.net.util.SocketExceptions;
3639

@@ -367,10 +370,13 @@ <A> Future<Void> implConnect(SocketAddress remote,
367370
* result when the read completes.
368371
*/
369372
private class ReadTask<V,A> implements Runnable, Iocp.ResultHandler {
373+
private static final VarHandle RELEASED = MhUtil.findVarHandle(MethodHandles.lookup(),
374+
"released", boolean.class);
370375
private final ByteBuffer[] bufs;
371376
private final int numBufs;
372377
private final boolean scatteringRead;
373378
private final PendingFuture<V,A> result;
379+
private volatile boolean released;
374380

375381
// set by run method
376382
private ByteBuffer[] shadow;
@@ -461,12 +467,14 @@ void updateBuffers(int bytesRead) {
461467
}
462468

463469
void releaseBuffers() {
464-
for (int i=0; i<numBufs; i++) {
465-
if (!(bufs[i] instanceof DirectBuffer)) {
466-
Util.releaseTemporaryDirectBuffer(shadow[i]);
470+
if (RELEASED.compareAndSet(this, false, true)) {
471+
for (int i = 0; i < numBufs; i++) {
472+
if (!(bufs[i] instanceof DirectBuffer)) {
473+
Util.releaseTemporaryDirectBuffer(shadow[i]);
474+
}
467475
}
476+
IOUtil.releaseScopes(scopeHandleReleasers);
468477
}
469-
IOUtil.releaseScopes(scopeHandleReleasers);
470478
}
471479

472480
@Override
@@ -641,10 +649,13 @@ public void run() {
641649
* result when the write completes.
642650
*/
643651
private class WriteTask<V,A> implements Runnable, Iocp.ResultHandler {
652+
private static final VarHandle RELEASED = MhUtil.findVarHandle(MethodHandles.lookup(),
653+
"released", boolean.class);
644654
private final ByteBuffer[] bufs;
645655
private final int numBufs;
646656
private final boolean gatheringWrite;
647657
private final PendingFuture<V,A> result;
658+
private volatile boolean released;
648659

649660
// set by run method
650661
private ByteBuffer[] shadow;
@@ -728,12 +739,14 @@ void updateBuffers(int bytesWritten) {
728739
}
729740

730741
void releaseBuffers() {
731-
for (int i=0; i<numBufs; i++) {
732-
if (!(bufs[i] instanceof DirectBuffer)) {
733-
Util.releaseTemporaryDirectBuffer(shadow[i]);
742+
if (RELEASED.compareAndSet(this, false, true)) {
743+
for (int i = 0; i < numBufs; i++) {
744+
if (!(bufs[i] instanceof DirectBuffer)) {
745+
Util.releaseTemporaryDirectBuffer(shadow[i]);
746+
}
734747
}
748+
IOUtil.releaseScopes(scopeHandleReleasers);
735749
}
736-
IOUtil.releaseScopes(scopeHandleReleasers);
737750
}
738751

739752
@Override

0 commit comments

Comments
 (0)