fix(provisioner): close SSH client before reassign, close pipe reader#659
Conversation
provision() overwrote p.Client with a new SSH connection without closing the old one, leaking TCP sockets and goroutines. Also close the io.Pipe reader after wg.Wait() for completeness. Audit findings #14 (MEDIUM), NVIDIA#29 (LOW). Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
Pull Request Test Coverage Report for Build 21978700032Details
💛 - Coveralls |
There was a problem hiding this comment.
Pull request overview
This PR fixes two resource leak issues in the provisioner identified by an audit: an SSH client that was being overwritten without closing, and an io.Pipe reader that was never closed. The changes prevent resource leaks by properly closing these resources before reassignment and after use.
Changes:
- Added SSH client close guard in
provision()before creating new connection - Added io.Pipe reader close after WaitGroup completes
|
|
||
| // Close existing client before creating new connection | ||
| if p.Client != nil { | ||
| _ = p.Client.Close() |
There was a problem hiding this comment.
The SSH client close logic here differs from the pattern used in resetConnection() and waitForNodeReboot(). Those functions check if the connection is still alive by attempting to create a session before closing. Consider using the same pattern here for consistency:
if p.Client != nil {
session, err := p.Client.NewSession()
if err == nil {
_ = session.Close()
if err := p.Client.Close(); err != nil {
return fmt.Errorf("failed to close ssh client: %w", err)
}
}
p.Client = nil
}
This prevents potential issues with closing already-dead connections and follows the established convention in the codebase.
| _ = p.Client.Close() | |
| // Try to create a new session to check if connection is alive | |
| session, err := p.Client.NewSession() | |
| if err == nil { | |
| _ = session.Close() | |
| // Connection is alive, close it | |
| if err := p.Client.Close(); err != nil { | |
| return fmt.Errorf("failed to close ssh client: %w", err) | |
| } | |
| } | |
| // If we get here, either the connection was already closed or we couldn't create a session |
Summary
provision()Audit Findings
Changes
pkg/provisioner/provisioner.go: Add client close guard + pipe reader closeTest plan
gofmt— no formatting issuesgo build— compilesgo test ./pkg/...— all tests pass