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

cleanup: prevent leaks from time.After #11983

Merged
merged 1 commit into from
Feb 3, 2022
Merged

cleanup: prevent leaks from time.After #11983

merged 1 commit into from
Feb 3, 2022

Conversation

shoenig
Copy link
Member

@shoenig shoenig commented Feb 2, 2022

This PR replaces use of time.After with a safe helper function
that creates a time.Timer to use instead. The new function returns
both a time.Timer and a Stop function that the caller must handle.

Unlike time.NewTimer, the helper function does not panic if the duration
set is <= 0.

Fixes #11982

@@ -177,15 +183,19 @@ func (s *execSession) startTransmit(ctx context.Context, conn *websocket.Conn) <

// send a heartbeat every 10 seconds
go func() {
t := time.NewTimer(heartbeatInterval)
Copy link
Member Author

Choose a reason for hiding this comment

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

helpers/ not available to api/, so no helper function here

  • make sure we call t.Stop
  • make sure the interval can never be non-positive

This PR replaces use of time.After with a safe helper function
that creates a time.Timer to use instead. The new function returns
both a time.Timer and a Stop function that the caller must handle.

Unlike time.NewTimer, the helper function does not panic if the duration
set is <= 0.
@vercel vercel bot temporarily deployed to Preview – nomad February 2, 2022 20:32 Inactive
@shoenig shoenig added this to the 1.3.0 milestone Feb 2, 2022
@shoenig shoenig marked this pull request as ready for review February 2, 2022 22:13
@shoenig shoenig requested review from lgfa29 and tgross February 2, 2022 22:14
Copy link
Member

@tgross tgross left a comment

Choose a reason for hiding this comment

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

LGTM 👍

Comment on lines +584 to +586
// Returns the time.Timer and also a StopFunc, forcing the caller to deal
// with stopping the time.Timer to avoid leaking a goroutine.
func NewSafeTimer(duration time.Duration) (*time.Timer, StopFunc) {
Copy link
Member

Choose a reason for hiding this comment

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

I really like the API on this. It makes it really obvious if we're accidentally misusing it by ex. calling NewSafeTimer inside the loop.

Copy link
Contributor

@lgfa29 lgfa29 left a comment

Choose a reason for hiding this comment

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

Nice helper 👍

I used this semgrep rule and it find some other instance of this pattern:

rules:
  - id: "time-after-leak"
    patterns:
      - pattern: |
          select {
          case <- time.After(...): ...
          }
    message: "Potential leak of timer"
    languages:
      - "go"
    severity: "WARNING"
    paths:
      exclude:
        - "testutil/*"
        - "*testing.go"
        - "*_test.go"

But I don't know if the are all valid or if there are any false positives.

@shoenig
Copy link
Member Author

shoenig commented Feb 3, 2022

I think that's a valid rule @lgfa29 in theory you don't need the for to leak the goroutines; it'll happen each time the enclosing function is called. Want to open a PR? And have the message point them towards NewSafeTimer

@shoenig shoenig merged commit 4f56d81 into main Feb 3, 2022
@shoenig shoenig deleted the b-select-after branch February 3, 2022 15:38
@lgfa29
Copy link
Contributor

lgfa29 commented Feb 3, 2022

I think that's a valid rule @lgfa29 in theory you don't need the for to leak the goroutines; it'll happen each time the enclosing function is called. Want to open a PR? And have the message point them towards NewSafeTimer

Yeah, good idea, I will update the message 👍

@github-actions
Copy link

I'm going to lock this pull request because it has been closed for 120 days ⏳. This helps our maintainers find and focus on the active contributions.
If you have found a problem that seems related to this change, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Oct 18, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
backport/1.1.x backport to 1.1.x release line backport/1.2.x backport to 1.1.x release line
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Prevent leaks from time.After
3 participants