googleapis / googleapis/google-cloud-java

[java-bigquery] [BigQuery] Thread will hang forever when using executeSelect if you do not iterate over the entire ResultSet

Đang mở
#12,149 3 bình luận 0 reaction 0 người được giao Xem trên GitHub
api: bigquery priority: p3 type: bug
Ngôn ngữ chính
Java
Star
2.1k
Fork
1.2k
Merge trung bình
1 ngày 23 giờ
Pull request đã merge (30 ngày)
154

Mô tả

Testing executeSelect on Java 21 on MacOS Sonoma 14.7.6, I found a concerning issue. If your process or thread attempts to end after creating a connection and calling `executeSelect()` without iterating over the entire ResultSet until `next()` returns false, it will hang forever.

#### Steps to reproduce

1. Go through the usual steps of instantiating a BigQuery client, creating ConnectionSettings, calling `createConnection` on said client, and then call `executeSelect()` to get your BigQueryResult.
2. Either let the process end, or don't iterate over the entire ResultSet contained in the BigQueryResult. It will hang.

#### Code example

```java
import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryResult;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.Connection;
import com.google.cloud.bigquery.ConnectionSettings;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.stream.Collectors;
import java.sql.ResultSet;
import java.sql.SQLException;

public class BQExecuteSelectTest {
public static void main(String[] args) {
try {
if(args.length != 2)
throw new IllegalArgumentException("Usage: BQExecuteSelectTest \n - Accepts SQL on STDIN");

BigQuery bq = BigQueryOptions.newBuilder()
.setProjectId(args[0])
.setLocation(args[1]).build().getService();

ConnectionSettings settings = ConnectionSettings.newBuilder()
.setCreateSession(true)
.setMaxResultPerPage(100)
.setMaxResults(100L).build();

Connection conn = bq.createConnection(settings);

BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
BigQueryResult res = conn.executeSelect(reader.lines().collect(Collectors.joining("\n")));

// Do nothing, or just don't finish iterating over res.getResultSet()
} catch(IllegalArgumentException e) {
System.out.println(e.getMessage());
} catch(Exception e) {
System.out.println("Something went wrong: " + e.getMessage());
}
}
}
```

#### Output
```
user@host bq_test % java -cp deps.jar:. BQExecuteSelectTest my-project us-east4 < test.sql
Jul 10, 2025 12:37:30 PM com.google.cloud.bigquery.ConnectionImpl getExecuteSelectResponse
INFO:
Using Fast Query Path
^C% <-- Hit Ctrl-C here after waiting for several minutes.
user@host bq_test %
```

#### External references such as API reference guides

- https://cloud.google.com/blog/topics/developers-practitioners/introducing-executeselect-client-library-method-and-how-use-it/

#### Any additional information below

When running a single command like this, you can simply Ctrl-C to end the process. But in a server environment where this could be running in different threads, it's very problematic. If a system (like mine) can allow interruption of ResultSet iteration (which can be necessary for very large result sets in specific scenarios), it can cause client threads to hang forever and never return, or background workers to wait forever and never become available to process other jobs.

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.