Skip to content

fix(grpc): avoid nil conn panic when close races asyncInvoke - #6247

Draft
cursor[bot] wants to merge 2 commits into
masterfrom
cursor/critical-bug-investigation-f761
Draft

fix(grpc): avoid nil conn panic when close races asyncInvoke#6247
cursor[bot] wants to merge 2 commits into
masterfrom
cursor/critical-bug-investigation-f761

Conversation

@cursor

@cursor cursor Bot commented Aug 5, 2026

Copy link
Copy Markdown

What?

Capture the gRPC connection before spawning the AsyncInvoke goroutine so client.close() cannot nil c.conn out from under Invoke.

Why?

AsyncInvoke checked c.conn != nil on the VU event loop, then launched a goroutine that called c.conn.Invoke(...). As soon as asyncInvoke() returned, JS could call client.close(), which sets c.conn = nil. When the goroutine then ran, it paniced:

panic: runtime error: invalid memory address or nil pointer dereference
go.k6.io/k6/v2/internal/lib/netext/grpcext.(*Conn).Invoke(0x0, ...)
go.k6.io/k6/v2/internal/js/modules/k6/grpc.(*Client).AsyncInvoke.func1

Trigger:

client.connect(addr);
const p = client.asyncInvoke('service/Method', {});
client.close(); // before await
await p; // process crash

Impact: process crash (SIGSEGV) on a documented API combination. Independent of the grpc-go v1.83.0 bump (#6240); the nil is k6's Client.conn field.

Using a closed-but-non-nil connection returns a gRPC error instead of panicking.

Checklist

  • I have performed a self-review of my code.
  • I have commented on my code, particularly in hard-to-understand areas.
  • I have added tests for my changes.
  • I have run linter and tests locally (make check) and all pass. (Focused: go test -race on ./internal/js/modules/k6/grpc/, go vet.)

Checklist: Documentation (only for k6 maintainers and if relevant)

  • I have added the correct milestone and labels to the PR.
  • I have updated the release notes: link
  • I have updated or added an issue to the k6-documentation: grafana/k6-docs#NUMBER if applicable
  • I have updated or added an issue to the TypeScript definitions: grafana/k6-DefinitelyTyped#NUMBER if applicable

Related PR(s)/Issue(s)

Validation

  • Forced-sleep repro panicked at grpcext.(*Conn).Invoke(0x0) before the fix
  • TestAsyncInvokeCloseDoesNotPanic passes under -race -count=5 after the fix
  • go test -race ./internal/js/modules/k6/grpc/ -run 'TestClient$|TestAsyncInvoke' passes
Open in Web View Automation 

cursoragent and others added 2 commits August 5, 2026 11:09
Capture the gRPC connection before spawning the AsyncInvoke goroutine so
client.close() cannot nil c.conn out from under Invoke and crash the
process with a nil pointer dereference.

Closes a user-facing crash trigger: asyncInvoke() followed by close()
before the promise settles.

Co-authored-by: Inanc Gumus <github@inanc.io>
Rely on the event loop waiting for the promise to settle; either
fulfillment or rejection after close is acceptable. The regression is
absence of a nil-conn panic.

Co-authored-by: Inanc Gumus <github@inanc.io>
@cla-assistant

cla-assistant Bot commented Aug 5, 2026

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@cursor
cursor Bot temporarily deployed to azure-trusted-signing August 5, 2026 11:16 Inactive
@cursor
cursor Bot temporarily deployed to azure-trusted-signing August 5, 2026 11:18 Inactive
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant