Skip to content

Commit bd4f570

Browse files
committed
vz: only ignore expected connection-closed errors in Shutdown
Previously Client.Shutdown returned nil for any httpClient.Do error, masking real failures (e.g. socket unreachable, connection refused) as successful shutdowns. This could leave orphaned vz-shim processes. Now only expected connection-closed errors (EOF, ECONNRESET, EPIPE, net.ErrClosed) are treated as successful shutdown indicators. All other transport errors are propagated to the caller so higher layers can detect and react to actual failures.
1 parent cc8413b commit bd4f570

File tree

1 file changed

+19
-2
lines changed

1 file changed

+19
-2
lines changed

lib/hypervisor/vz/client.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@ package vz
55
import (
66
"context"
77
"encoding/json"
8+
"errors"
89
"fmt"
910
"io"
1011
"net"
1112
"net/http"
13+
"syscall"
1214
"time"
1315

1416
"github.com/kernel/hypeman/lib/hypervisor"
@@ -116,13 +118,28 @@ func (c *Client) Shutdown(ctx context.Context) error {
116118
}
117119
resp, err := c.httpClient.Do(req)
118120
if err != nil {
119-
// Connection reset is expected when shim exits
120-
return nil
121+
// Connection reset / EOF is expected when the shim exits in
122+
// response to the shutdown request. Any other error means the
123+
// request may not have reached the shim.
124+
if isExpectedShutdownError(err) {
125+
return nil
126+
}
127+
return fmt.Errorf("shutdown shim: %w", err)
121128
}
122129
defer resp.Body.Close()
123130
return nil
124131
}
125132

133+
// isExpectedShutdownError reports whether err is a connection-closed error
134+
// that is expected when the vz-shim process exits after handling a shutdown
135+
// request.
136+
func isExpectedShutdownError(err error) bool {
137+
return errors.Is(err, io.EOF) ||
138+
errors.Is(err, syscall.ECONNRESET) ||
139+
errors.Is(err, syscall.EPIPE) ||
140+
errors.Is(err, net.ErrClosed)
141+
}
142+
126143
func (c *Client) GetVMInfo(ctx context.Context) (*hypervisor.VMInfo, error) {
127144
body, err := c.doGet(ctx, "/api/v1/vm.info")
128145
if err != nil {

0 commit comments

Comments
 (0)