Changeset: 85e657dfa8af for MonetDB URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=85e657dfa8af Modified Files: java/embedded/src/main/java/org/monetdb/embedded/result/EmbeddedQueryResult.java java/embedded/src/test/java/org/monetdb/embedded/test/EmbeddedTest.java Branch: embedded-java Log Message:
Avoid segfault when accessing cleaned-up resources Simply check if it cleaned-up and do not allow access. Returns null on column get. Can produce NullPointerExceptions, but prevents segfaults and JVM crashes. Add a unit test of that While there - minor var cleanup diffs (106 lines): diff --git a/java/embedded/src/main/java/org/monetdb/embedded/result/EmbeddedQueryResult.java b/java/embedded/src/main/java/org/monetdb/embedded/result/EmbeddedQueryResult.java --- a/java/embedded/src/main/java/org/monetdb/embedded/result/EmbeddedQueryResult.java +++ b/java/embedded/src/main/java/org/monetdb/embedded/result/EmbeddedQueryResult.java @@ -75,6 +75,11 @@ public class EmbeddedQueryResult impleme if (index >= numberOfColumns || index < 0) { return null; } + if (resultPointer == 0) { + // The object was closed and result was cleaned-up + // Calling the can produce a native Segfault (and crash the JVM) + return null; + } return getColumnWrapper(resultPointer, index); } @@ -133,7 +138,10 @@ public class EmbeddedQueryResult impleme @Override public void close() throws IOException { - cleanupResult(resultPointer); + if (resultPointer > 0) { + cleanupResult(resultPointer); + resultPointer = 0; + } } /** diff --git a/java/embedded/src/test/java/org/monetdb/embedded/test/EmbeddedTest.java b/java/embedded/src/test/java/org/monetdb/embedded/test/EmbeddedTest.java --- a/java/embedded/src/test/java/org/monetdb/embedded/test/EmbeddedTest.java +++ b/java/embedded/src/test/java/org/monetdb/embedded/test/EmbeddedTest.java @@ -16,8 +16,10 @@ import java.nio.file.Files; import java.nio.file.Path; import java.sql.SQLException; import java.util.Iterator; +import java.util.concurrent.TimeUnit; import org.junit.BeforeClass; +import org.junit.Ignore; import org.junit.Test; import org.monetdb.embedded.MonetDBEmbedded; import org.monetdb.embedded.result.EmbeddedQueryResult; @@ -49,11 +51,12 @@ public class EmbeddedTest { }; @BeforeClass - public static void createTestDB() throws IOException, SQLException { + public static void createTestDB() throws IOException, SQLException, InterruptedException { final Path directoryPath = Files.createTempDirectory("monetdbtest"); datbaseDirectory = directoryPath.toFile(); db = new MonetDBEmbedded(datbaseDirectory); +// TimeUnit.SECONDS.sleep(15); db.start(); db.query("CREATE TABLE test (id integer, val integer);"); @@ -187,9 +190,6 @@ public class EmbeddedTest { assertEquals(2, result1.getColumn(1).columnSize()); assertEquals(testValues[1][2], result1.getColumn(1).getValue(0)); assertEquals(testValues[1][3], result1.getColumn(1).getValue(1)); - - result1.close(); - result2.close(); } @Test @@ -198,7 +198,6 @@ public class EmbeddedTest { assertEquals(2, result1.getColumn(1).columnSize()); assertEquals(testValues[1][2], result1.getColumn(1).getValue(0)); assertEquals(testValues[1][3], result1.getColumn(1).getValue(1)); - result1.close(); EmbeddedQueryResult result2 = db.query("SELECT * FROM test WHERE id < 1;"); assertEquals(testValues[1][0], result2.getColumn(1).getValue(0)); @@ -221,6 +220,32 @@ public class EmbeddedTest { result.close(); } + + @Test + public void dobuleManualCleanupTest() throws IOException, SQLException { + @SuppressWarnings("resource") + EmbeddedQueryResult result = db.query("SELECT * FROM test;"); + assertEquals(4, result.getColumn(1).columnSize()); + assertEquals(Integer.valueOf(20), result.getColumn(1).getValue(1)); + assertEquals(null, result.getColumn(1).getValue(3)); + + result.close(); + result.close(); + } + + @Test + public void resultAccessAfterClose() throws IOException, SQLException { + @SuppressWarnings("resource") + EmbeddedQueryResult result = db.query("SELECT * FROM test;"); + assertEquals(4, result.getColumn(1).columnSize()); + assertEquals(Integer.valueOf(20), result.getColumn(1).getValue(1)); + assertEquals(null, result.getColumn(1).getValue(3)); + + result.close(); + + // The result of any column get should be null + assertEquals(null, result.getColumn(1)); + } @Test(expected=SQLException.class) public void captureQueryErrorTest() throws SQLException { _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list