Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Linter ignores span.End if called inside deferred function #12

Closed
bmon opened this issue Feb 22, 2024 · 1 comment · Fixed by #13
Closed

[BUG] Linter ignores span.End if called inside deferred function #12

bmon opened this issue Feb 22, 2024 · 1 comment · Fixed by #13
Labels
bug Something isn't working

Comments

@bmon
Copy link

bmon commented Feb 22, 2024

Describe the bug
I have some code that calls span.End() inside a deferred function because I also want to trap and record panics via recover().

Unfortunately this linter does not recognise that span.End() is called in the deferred function, and reports span.End is not called on all paths, possible memory leak

To Reproduce

package main

import (
	"context"

	"go.opentelemetry.io/otel"
)

func _() {
	_, span := otel.Tracer("foo").Start(context.Background(), "bar")
	defer func() {
		span.End()
	}()
}
$ spancheck ./...
/home/brendan/git/go-spancheck/testdata/base/defer.go:10:2: span.End is not called on all paths, possible memory leak
/home/brendan/git/go-spancheck/testdata/base/defer.go:14:1: return can be reached without calling span.End
exit status 3

Expected behavior
The linter recognises this as a safe span completion that cannot be skipped and won't leak spans.

@bmon bmon added the bug Something isn't working label Feb 22, 2024
@jjti jjti closed this as completed in #13 Feb 23, 2024
@jjti
Copy link
Owner

jjti commented Feb 23, 2024

Hey @bmon , thank you for pointing this point and giving a great+detailed example. I tried to address it here: #13

It'll now check FuncLiterals (1 level deep) for span calls like End() as in your example:

// This tests that we detect when the span is closed within a deferred func.
// https://github.com/jjti/go-spancheck/issues/12
func _() {
	_, span := otel.Tracer("foo").Start(context.Background(), "bar")
	defer func() {
		span.End()
	}()
}

// Despite above, we do not wander more than one level deep into the defer stack.
func _() {
	_, span := otel.Tracer("foo").Start(context.Background(), "bar") // want "span.End is not called on all paths, possible memory leak"
	defer func() {
		defer func() {
			span.End()
		}()
	}()
} // want "return can be reached without calling span.End"

I hope you'll try it out! It will be awhile before this fix is available in Golangci, tho

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants