8220477: Channels.newWriter() does not close if underlying channel throws an IOException

Reviewed-by: alanb
This commit is contained in:
Brian Burkhalter 2019-04-17 08:12:19 -07:00
parent 7b7f9a6fd3
commit 69ca2e9e27
3 changed files with 142 additions and 22 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -28,10 +28,20 @@
package sun.nio.cs;
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.io.Reader;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CoderResult;
import java.nio.charset.CodingErrorAction;
import java.nio.charset.IllegalCharsetNameException;
public class StreamDecoder extends Reader
{
@ -190,10 +200,13 @@ public class StreamDecoder extends Reader
synchronized (lock) {
if (closed)
return;
try {
implClose();
} finally {
closed = true;
}
}
}
private boolean isOpen() {
return !closed;

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -23,15 +23,21 @@
* questions.
*/
/*
*/
package sun.nio.cs;
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.WritableByteChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.nio.charset.CodingErrorAction;
import java.nio.charset.IllegalCharsetNameException;
public class StreamEncoder extends Writer
{
@ -158,10 +164,13 @@ public class StreamEncoder extends Writer
synchronized (lock) {
if (closed)
return;
try {
implClose();
} finally {
closed = true;
}
}
}
private boolean isOpen() {
return !closed;
@ -337,8 +346,13 @@ public class StreamEncoder extends Writer
writeBytes();
if (ch != null)
ch.close();
else
else {
try {
out.flush();
} finally {
out.close();
}
}
} catch (IOException x) {
encoder.reset();
throw x;

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -22,7 +22,7 @@
*/
/* @test
* @bug 4417152 4481572 6248930 6725399 6884800
* @bug 4417152 4481572 6248930 6725399 6884800 8220477
* @summary Test Channels basic functionality
*/
@ -31,7 +31,6 @@ import java.nio.*;
import java.nio.charset.*;
import java.nio.channels.*;
public class Basic {
static String message;
@ -204,6 +203,8 @@ public class Basic {
writeOut(blah, ITERATIONS);
testNewReader(blah);
testNewWriterClose();
testNewReaderClose();
} finally {
blah.delete();
}
@ -399,6 +400,98 @@ public class Basic {
r.close();
fis.close();
}
private static void testNewWriterClose() throws Exception {
Writer writer = null;
try {
WritableByteChannel channel = new WritableByteChannel() {
@Override
public int write(ByteBuffer src) throws IOException {
return 0;
}
@Override
public boolean isOpen() {
return true;
}
@Override
public void close() throws IOException {
throw new IOException();
}
};
writer = Channels.newWriter(channel,
StandardCharsets.UTF_8.newEncoder(), -1);
writer.close();
} catch (IOException ioe) {
Exception theException = null;
try {
writer.write(1);
writer.flush();
} catch (Exception e) {
theException = e;
} finally {
if (theException == null) {
throw new RuntimeException("IOException not thrown");
} else if (!(theException instanceof IOException)) {
throw new RuntimeException("Exception not an IOException: "
+ theException);
} else {
String message = theException.getMessage();
if (!message.equals("Stream closed")) {
throw new RuntimeException("Unexpected message "
+ message);
}
}
}
}
}
private static void testNewReaderClose() throws Exception {
Reader reader = null;
try {
ReadableByteChannel channel = new ReadableByteChannel() {
@Override
public int read(ByteBuffer dst) throws IOException {
dst.put((byte)7);
return 1;
}
@Override
public boolean isOpen() {
return true;
}
@Override
public void close() throws IOException {
throw new IOException();
}
};
reader = Channels.newReader(channel,
StandardCharsets.UTF_8.newDecoder(), -1);
reader.close();
} catch (IOException ioe) {
Exception theException = null;
try {
reader.read();
} catch (Exception e) {
theException = e;
} finally {
if (theException == null) {
throw new RuntimeException("IOException not thrown");
} else if (!(theException instanceof IOException)) {
throw new RuntimeException("Exception not an IOException: "
+ theException);
} else {
String message = theException.getMessage();
if (!message.equals("Stream closed")) {
throw new RuntimeException("Unexpected message "
+ message);
}
}
}
}
}
}
class ExtendedFileInputStream extends java.io.FileInputStream {