Native SIGSEGV in DuckDB JDBC when repeatedly executing queries with window functions and LIMIT 0
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 48/100
Research direction
Start by compiling repro/DuckDBVpCrash1279455Stable.java with the provided JDBC jar and run it in both source and split modes. Confirm the repeated LIMIT 0 queries crash in duckdb_jdbc_execute_pending rather than returning an empty result set, then trace the JDBC/native execution path to identify the failure and verify clean completion in both modes.
Written by the indexing model from the issue text.
Description
What happens?
Repeatedly executing a query that contains a window function (RANK() OVER (...)), an ORDER BY, and a LIMIT 0 causes a native SIGSEGV crash in DuckDB JDBC. The JVM process is aborted with exit code 134. The crash occurs in org.duckdb.DuckDBNative.duckdb_jdbc_execute_pending.
The crash is reproducible in both the source mode (single-table query) and the split mode (split query), running single-threaded with threads=1. Both queries use LIMIT 0 and should return an empty result set without crashing.
To Reproduce
Driver
Use DuckDB JDBC:
<dependency>
<groupId>org.duckdb</groupId>
<artifactId>duckdb_jdbc</artifactId>
<version>1.5.5.1</version>
</dependency>
Reproducer
Save the following as repro/DuckDBVpCrash1279455Stable.java:
import java.nio.file.Files;
import java.nio.file.Path;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
/**
* Stable minimized reproducer for the DuckDB JDBC native crash observed in
* hs_err_pid1279455.log from SQLancer's VP split side.
*
* Shape preserved from the crash context:
* - split-side query
* - disabled_optimizers='filter_pushdown,join_order'
* - RANK() OVER (...) over a reconstructed VP relation
* - right side pre-aggregated by row id and joined back
* - ORDER BY ... LIMIT 0
*
* Tested with org.duckdb:duckdb_jdbc:1.5.5.1 on OpenJDK 17.
*/
public final class DuckDBVpCrash1279455Stable {
private static String sourceQuery(String sourceTable) {
return """
SELECT RANK() OVER (ORDER BY vp_rowid, vp_rowid)
FROM %s
ORDER BY vp_rowid
LIMIT 0
""".formatted(sourceTable);
}
private static String splitQuery(String leftTable, String rightTable) {
return """
SELECT RANK() OVER (ORDER BY vp_rowid, vp_rowid)
FROM (
SELECT l.vp_rowid AS vp_rowid, r.c7 AS c7
FROM %s l
JOIN (SELECT vp_rowid, COUNT(*) AS vp_count FROM %s GROUP BY vp_rowid) rg
ON l.vp_rowid = rg.vp_rowid
JOIN %s r
ON r.vp_rowid = rg.vp_rowid
) vp_source
ORDER BY vp_source.vp_rowid
LIMIT 0
""".formatted(leftTable, rightTable, rightTable);
}
private DuckDBVpCrash1279455Stable() {
}
public static void main(String[] args) throws Exception {
int repetitions = args.length == 0 ? 200 : Integer.parseInt(args[0]);
String logId = args.length < 2 ? "1279455" : sanitize(args[1]);
String mode = args.length < 3 ? "split" : args[2].toLowerCase();
if (!mode.equals("source") && !mode.equals("split")) {
throw new IllegalArgumentException("mode must be 'source' or 'split'");
}
boolean sourceOnly = mode.equals("source");
Path databaseFile = Path.of("repro_duckdb" + logId + "_db_min.duckdb").toAbsolutePath();
String sourceTable = "source_" + logId;
String leftTable = "left_" + logId;
String rightTable = "right_" + logId;
Path tempDirectory = Files.createTempDirectory("duckdb-vp-crash-1279455-");
// Start from a fresh, named DuckDB database file so the developer only
// needs to compile and run this JDBC file.
Files.deleteIfExists(databaseFile);
Files.deleteIfExists(Path.of(databaseFile + ".wal"));
try (Connection connection = DriverManager.getConnection("jdbc:duckdb:" + databaseFile);
Statement statement = connection.createStatement()) {
statement.execute("SET threads=1");
statement.execute("SET temp_directory='"
+ tempDirectory.toAbsolutePath().toString().replace("'", "''") + "'");
statement.execute("""
CREATE TABLE %s AS
SELECT i AS vp_rowid,
TIMESTAMP '2000-01-01' + CAST(i AS INTEGER) * INTERVAL '1 second' AS c7
FROM range(100) t(i)
""".formatted(sourceTable));
statement.execute("CREATE TABLE " + leftTable + " AS SELECT vp_rowid FROM " + sourceTable);
statement.execute("CREATE TABLE " + rightTable + " AS SELECT vp_rowid, c7 FROM " + sourceTable);
statement.execute("SET disabled_optimizers='filter_pushdown,join_order'");
String splitQuery = splitQuery(leftTable, rightTable);
String query = sourceOnly ? sourceQuery(sourceTable) : splitQuery;
for (int i = 1; i <= repetitions; i++) {
try (ResultSet resultSet = statement.executeQuery(query)) {
if (resultSet.next()) {
throw new AssertionError("LIMIT 0 query unexpectedly returned a row");
}
}
if (i == 1 || i % 10 == 0) {
System.out.println(mode + " repetitions=" + i);
}
}
System.out.println("completed without native crash");
}
}
private static String sanitize(String value) {
String sanitized = value.replaceAll("[^A-Za-z0-9_]", "_");
return sanitized.isEmpty() ? "1279455" : sanitized;
}
}
Compile
mkdir -p /tmp/duckdb-vp-repro-classes
javac \
-cp target/lib/duckdb_jdbc-1.5.5.1.jar \
-d /tmp/duckdb-vp-repro-classes \
repro/DuckDBVpCrash1279455Stable.java
Run in source mode
timeout 45s java \
-cp '/tmp/duckdb-vp-repro-classes:target/lib/duckdb_jdbc-1.5.5.1.jar' \
DuckDBVpCrash1279455Stable 200 1279455 source
Run in split mode
timeout 45s java \
-cp '/tmp/duckdb-vp-repro-classes:target/lib/duckdb_jdbc-1.5.5.1.jar' \
DuckDBVpCrash1279455Stable 200 1279455 split
Argument meanings:
200 repeat the query 200 times
1279455 log / case id, used to generate database and table names
source run the source query
split run the VP split query
The reproducer automatically:
- creates the database file;
- creates the test tables;
- inserts 100 rows of deterministic data;
- sets
threads=1; - sets
SET disabled_optimizers='filter_pushdown,join_order'; - repeatedly executes the query.
Actual result
Both source and split modes cause the JVM to crash inside DuckDB native code:
SIGSEGV (0xb)
Problematic frame:
C [libc.so.6+...]
Typical Java stack:
org.duckdb.DuckDBNative.duckdb_jdbc_execute_pending
org.duckdb.DuckDBPreparedStatement.execute
org.duckdb.DuckDBPreparedStatement.executeQuery
DuckDBVpCrash1279455Stable.main
Process exit code is typically:
134
Expected result
Because the queries use LIMIT 0, they should:
- return an empty result set normally;
- let the Java program exit cleanly;
and should not cause:
SIGSEGV
Aborted (core dumped)
JVM native crash
OS:
Ubuntu 20.04.6 LTS, x86_64
DuckDB Version:
v1.5.5
DuckDB Client:
Java JDBC
Hardware:
Intel Xeon Gold 5218R, 80 cores, 1486G RAM
Full Name:
Annie liu
Affiliation:
ECNU
Did you include all relevant configuration (e.g., CPU architecture, Linux distribution) to reproduce the issue?
- Yes, I have
Did you include all code required to reproduce the issue?
- Yes, I have
Did you include all relevant data sets for reproducing the issue?
Yes
- Dominant language
- C++
- Stars
- 127
- Forks
- 80
- Avg merge
- 13h 41m
- Merged PRs (30d)
- 44
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from duckdb/duckdb-java
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
duckdb/duckdb-java#832 · 2 comments ·
-
Difficulty 4/5 3-5 days Newbie friendliness 45/100
duckdb/duckdb-java#872 ·
-
Difficulty 5/5 Over a week Newbie friendliness 35/100
duckdb/duckdb-java#837 ·
-
executeBatch()` on a prepared INSERT runs s are ~1–2 orders of magnitude slower than the Appender Open
Difficulty 5/5 Over a week Newbie friendliness 42/100
duckdb/duckdb-java#815 · 1 comment ·
-
capi_v2
Difficulty 5/5 Over a week Newbie friendliness 35/100
duckdb/duckdb-java#806 · 1 comment ·
All issues in duckdb/duckdb-java
Similar issues
-
Difficulty 1/5 Under an hour Newbie friendliness 90/100
AXERA-TECH/ax-llm#77 ·
-
Difficulty 1/5 Under an hour Newbie friendliness 90/100
games-on-whales/wolf#509 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
-
bug-unconfirmed
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
NVIDIA/cuda-samples#453 ·