Skip to content

Commit 410175c

Browse files
committed
[CSV-318] CSVPrinter.printRecord(Stream) hangs if given a parallel
stream
1 parent bf09a8b commit 410175c

File tree

3 files changed

+12
-23
lines changed

3 files changed

+12
-23
lines changed

src/changes/changes.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
<body>
4343
<release version="1.14.1" date="YYYY-MM-DD" description="This is a feature and maintenance release. Java 8 or later is required.">
4444
<!-- FIX -->
45+
<action type="fix" issue="CSV-318" dev="ggregory" due-to="Joseph Shraibman, Gary Gregory">CSVPrinter.printRecord(Stream) hangs if given a parallel stream.</action>
4546
<!-- ADD -->
4647
<!-- UPDATE -->
4748
<action type="update" dev="ggregory" due-to="Gary Gregory">Bump commons-io:commons-io from 2.18.0 to 2.19.0.</action>

src/main/java/org/apache/commons/csv/CSVPrinter.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import java.sql.Statement;
3636
import java.util.Arrays;
3737
import java.util.Objects;
38+
import java.util.concurrent.locks.ReentrantLock;
3839
import java.util.stream.Stream;
3940

4041
import org.apache.commons.io.function.IOStream;
@@ -87,6 +88,8 @@ public final class CSVPrinter implements Flushable, Closeable {
8788
private boolean newRecord = true;
8889

8990
private long recordCount;
91+
92+
private ReentrantLock lock = new ReentrantLock();
9093

9194
/**
9295
* Creates a printer that will print values to the given stream following the CSVFormat.
@@ -326,9 +329,14 @@ public void printRecord(final Object... values) throws IOException {
326329
* @since 1.10.0
327330
*/
328331
@SuppressWarnings("resource") // caller closes.
329-
public synchronized void printRecord(final Stream<?> values) throws IOException {
330-
IOStream.adapt(values).forEachOrdered(this::print);
331-
endOfRecord();
332+
public void printRecord(final Stream<?> values) throws IOException {
333+
lock.lock();
334+
try {
335+
IOStream.adapt(values).forEachOrdered(this::print);
336+
endOfRecord();
337+
} finally {
338+
lock.unlock();
339+
}
332340
}
333341

334342
private void printRecordObject(final Object value) throws IOException {

src/test/java/org/apache/commons/csv/JiraCsv318Test.java

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
import org.apache.commons.io.function.IOConsumer;
3232
import org.apache.commons.io.function.IOStream;
3333
import org.apache.commons.lang3.ArrayUtils;
34-
import org.junit.jupiter.api.Disabled;
3534
import org.junit.jupiter.api.Test;
3635

3736
/**
@@ -67,10 +66,6 @@ private Stream<String> newStream() {
6766
return Stream.of("col a", "col b", "col c");
6867
}
6968

70-
public synchronized void printRecord(final Stream<?> values) throws IOException {
71-
// IOStream.adapt(values).forEachOrdered(this::print);
72-
}
73-
7469
@Test
7570
void testDefaultStream() throws IOException {
7671
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -91,20 +86,6 @@ void testParallelIOStream() throws IOException {
9186
checkOutput(baos);
9287
}
9388

94-
@SuppressWarnings("resource")
95-
@Test
96-
@Disabled("Deadlock because CSVPrinter.print(Object) is synchronized")
97-
void testParallelIOStreamSynchronizedPrinter() throws IOException {
98-
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
99-
try (CSVPrinter printer = newPrinter(baos)) {
100-
synchronized (printer) {
101-
IOStream.adapt(newParallelStream()).forEachOrdered(printer::print);
102-
}
103-
}
104-
// No EOR marker in this test intentionally, so checkOutput will trim.
105-
checkOutput(baos);
106-
}
107-
10889
@SuppressWarnings("resource")
10990
@Test
11091
void testParallelIOStreamSynchronizedPrinterNotUsed() throws IOException {
@@ -125,7 +106,6 @@ void testParallelIOStreamSynchronizedPrinterNotUsed() throws IOException {
125106
}
126107

127108
@Test
128-
@Disabled("Deadlock because CSVPrinter.print(Object) is synchronized")
129109
void testParallelStream() throws IOException {
130110
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
131111
try (CSVPrinter printer = newPrinter(baos)) {

0 commit comments

Comments
 (0)