Skip to content

Conversation

@chavacava
Copy link
Collaborator

@chavacava chavacava commented Mar 16, 2025

This PR adds a new rule: time-after-leak
The rule spots the known problem of temporary leak of goroutines underlying time.After()

As described by the documentation of time.After(), version 1.23 of Go fixed the problem thus the rule skips files of packages with a Go version equal or higher than 1.23.

The PR also introduces lint.IsAtLeastGoVersion to factor-out the common code of lint.IsAtLeastGo1*

@chavacava chavacava requested a review from denisvmedia March 16, 2025 15:05
@denisvmedia
Copy link
Collaborator

Hi @chavacava thank you for the PR. I'm wondering if we really should introduce this rule, since go versions below 1.23 are already out of their life cycle. I do however like the idea of the improvements in the code you made.

Copy link
Collaborator

@denisvmedia denisvmedia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM (with a question about linting go projects with go version below 1.23)

@ccoVeille
Copy link
Contributor

I share @denisvmedia point of view, with one remark anyway:

I have read something yesterday about the fact the bug was only partially fixed for Go 1.23+

Meaning it's way better now, but it still leaks somehow in some circumstances.

I will have to find back where it was.

@ccoVeille
Copy link
Contributor

Found it back.

https://dev.to/iw4p/how-timeafter-can-cause-memory-leaks-in-go-and-how-to-fix-them-1kg3

Now,I'm doubting about the fact we can trust this article.

I mean I checked almost viable resources and found nothing about it.

Confidence: 0.8,
Node: call.Fun,
Category: lint.FailureCategoryBadPractice,
Failure: "the underlying goroutine of time.After() is not garbage-collected until timer expiration, prefer NewTimer+Timer.Stop",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this error message, you could mention one solution is also to upgrade to Go 1.23+

Or the opposite that this error exists only for version prior 1.23

The same way use-any mentions any can be used with Go 1.18+

https://github.com/mgechev/revive/blob/master/rule%2Fuse_any.go#L50

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I would like to suggest using a message like the one used for omitzero in structtag rule

return `prior Go 1.24, option "omitzero" is unsupported`, false

prior Go 1.24, option "omitzero" is unsupported

| [`redundant-build-tag`](./RULES_DESCRIPTIONS.md#redundant-build-tag) | n/a | Warns about redundant `// +build` comment lines | no | no |
| [`use-errors-new`](./RULES_DESCRIPTIONS.md#use-errors-new) | n/a | Spots calls to `fmt.Errorf` that can be replaced by `errors.New` | no | no |
| [`redundant-test-main-exit`](./RULES_DESCRIPTIONS.md#redundant-test-main-exit) | n/a | Suggests removing `Exit` call in `TestMain` function for test files | no | no |
| [`time-after-leak`](./RULES_DESCRIPTIONS.md#time-after-leak) | n/a | Suggests replacing `time.After` with `time.NewTimer` to prevent goroutine leak | no | no |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would mention here it's for older Go versions, or something like

Suggested change
| [`time-after-leak`](./RULES_DESCRIPTIONS.md#time-after-leak) | n/a | Suggests replacing `time.After` with `time.NewTimer` to prevent goroutine leak | no | no |
| [`time-after-leak`](./RULES_DESCRIPTIONS.md#time-after-leak) | n/a | Suggests replacing `time.After` with `time.NewTimer` to prevent goroutine leak, if needed | no | no |
Suggested change
| [`time-after-leak`](./RULES_DESCRIPTIONS.md#time-after-leak) | n/a | Suggests replacing `time.After` with `time.NewTimer` to prevent goroutine leak | no | no |
| [`time-after-leak`](./RULES_DESCRIPTIONS.md#time-after-leak) | n/a | Suggests replacing `time.After` with `time.NewTimer` to prevent goroutine leak for old Go versions | no | no |

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But maybe, one interesting thing could be to add a column to this table to mention the Go version specification

Something like < 1.23 here, and > 1.18 for use-any, and others.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[rule.superfluous-else]
arguments = ["preserveScope"]
```
## time-after-leak
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a new line before:

Suggested change
## time-after-leak
## time-after-leak


_Description_: This rule warns on temporary goroutine leak when using `time.After` in select statements. In Go versions before 1.23, [the garbage collector does not recover the underlying thread until the timer fires](https://pkg.go.dev/time#After).

_Configuration_: N/A
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I propose adding a note similar to the ones in range-val-address and range-val-in-closure:

Suggested change
_Configuration_: N/A
_Configuration_: N/A
_Note_: This rule is irrelevant for Go 1.23+.

@chavacava
Copy link
Collaborator Author

Closing. Niche rule for old Go version

@chavacava chavacava closed this May 9, 2025
@chavacava chavacava deleted the rule/time-after-leak branch May 22, 2025 19:45
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.

5 participants