Skip to content

Commit 80216d7

Browse files
authored
Add context argument to runner methods that do work (#273)
* Allows us to properly respect the start timeout for implementations that do long-running work in the Start method. * Adding context.Context to Wait and Kill makes them more consistent with Start, but is also a bit of a hedge, allowing room in the interface for future features without having to break the API.
1 parent 8b178aa commit 80216d7

File tree

5 files changed

+27
-19
lines changed

5 files changed

+27
-19
lines changed

client.go

+7-5
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ func (c *Client) Kill() {
515515

516516
// If graceful exiting failed, just kill it
517517
c.logger.Warn("plugin failed to exit gracefully")
518-
if err := runner.Kill(); err != nil {
518+
if err := runner.Kill(context.Background()); err != nil {
519519
c.logger.Debug("error killing plugin", "error", err)
520520
}
521521

@@ -668,7 +668,9 @@ func (c *Client) Start() (addr net.Addr, err error) {
668668
}
669669

670670
c.runner = runner
671-
err = runner.Start()
671+
startCtx, startCtxCancel := context.WithTimeout(context.Background(), c.config.StartTimeout)
672+
defer startCtxCancel()
673+
err = runner.Start(startCtx)
672674
if err != nil {
673675
return nil, err
674676
}
@@ -678,7 +680,7 @@ func (c *Client) Start() (addr net.Addr, err error) {
678680
rErr := recover()
679681

680682
if err != nil || rErr != nil {
681-
runner.Kill()
683+
runner.Kill(context.Background())
682684
}
683685

684686
if rErr != nil {
@@ -707,7 +709,7 @@ func (c *Client) Start() (addr net.Addr, err error) {
707709
c.stderrWaitGroup.Wait()
708710

709711
// Wait for the command to end.
710-
err := runner.Wait()
712+
err := runner.Wait(context.Background())
711713
if err != nil {
712714
c.logger.Error("plugin process exited", "plugin", runner.Name(), "id", runner.ID(), "error", err.Error())
713715
} else {
@@ -899,7 +901,7 @@ func (c *Client) reattach() (net.Addr, error) {
899901
defer c.ctxCancel()
900902

901903
// Wait for the process to die
902-
r.Wait()
904+
r.Wait(context.Background())
903905

904906
// Log so we can see it
905907
c.logger.Debug("reattached plugin process exited")

client_test.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package plugin
55

66
import (
77
"bytes"
8+
"context"
89
"crypto/sha256"
910
"fmt"
1011
"io"
@@ -226,7 +227,7 @@ func TestClient_grpc_servercrash(t *testing.T) {
226227
t.Fatalf("bad: %#v", raw)
227228
}
228229

229-
c.runner.Kill()
230+
c.runner.Kill(context.Background())
230231

231232
select {
232233
case <-c.doneCtx.Done():
@@ -1255,7 +1256,7 @@ func TestClient_versionedClient(t *testing.T) {
12551256
t.Fatalf("bad: %#v", raw)
12561257
}
12571258

1258-
c.runner.Kill()
1259+
c.runner.Kill(context.Background())
12591260

12601261
select {
12611262
case <-c.doneCtx.Done():
@@ -1311,7 +1312,7 @@ func TestClient_mtlsClient(t *testing.T) {
13111312
t.Fatal("invalid response", n)
13121313
}
13131314

1314-
c.runner.Kill()
1315+
c.runner.Kill(context.Background())
13151316

13161317
select {
13171318
case <-c.doneCtx.Done():
@@ -1357,7 +1358,7 @@ func TestClient_mtlsNetRPCClient(t *testing.T) {
13571358
t.Fatal("invalid response", n)
13581359
}
13591360

1360-
c.runner.Kill()
1361+
c.runner.Kill(context.Background())
13611362

13621363
select {
13631364
case <-c.doneCtx.Done():

internal/cmdrunner/cmd_reattach.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package cmdrunner
55

66
import (
7+
"context"
78
"fmt"
89
"net"
910
"os"
@@ -49,11 +50,11 @@ type CmdAttachedRunner struct {
4950
addrTranslator
5051
}
5152

52-
func (c *CmdAttachedRunner) Wait() error {
53+
func (c *CmdAttachedRunner) Wait(_ context.Context) error {
5354
return pidWait(c.pid)
5455
}
5556

56-
func (c *CmdAttachedRunner) Kill() error {
57+
func (c *CmdAttachedRunner) Kill(_ context.Context) error {
5758
return c.process.Kill()
5859
}
5960

internal/cmdrunner/cmd_runner.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package cmdrunner
55

66
import (
7+
"context"
78
"errors"
89
"fmt"
910
"io"
@@ -61,7 +62,7 @@ func NewCmdRunner(logger hclog.Logger, cmd *exec.Cmd) (*CmdRunner, error) {
6162
}, nil
6263
}
6364

64-
func (c *CmdRunner) Start() error {
65+
func (c *CmdRunner) Start(_ context.Context) error {
6566
c.logger.Debug("starting plugin", "path", c.cmd.Path, "args", c.cmd.Args)
6667
err := c.cmd.Start()
6768
if err != nil {
@@ -73,11 +74,11 @@ func (c *CmdRunner) Start() error {
7374
return nil
7475
}
7576

76-
func (c *CmdRunner) Wait() error {
77+
func (c *CmdRunner) Wait(_ context.Context) error {
7778
return c.cmd.Wait()
7879
}
7980

80-
func (c *CmdRunner) Kill() error {
81+
func (c *CmdRunner) Kill(_ context.Context) error {
8182
if c.cmd.Process != nil {
8283
err := c.cmd.Process.Kill()
8384
// Swallow ErrProcessDone, we support calling Kill multiple times.

runner/runner.go

+8-5
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,19 @@
44
package runner
55

66
import (
7+
"context"
78
"io"
89
)
910

1011
// Runner defines the interface required by go-plugin to manage the lifecycle of
1112
// of a plugin and attempt to negotiate a connection with it. Note that this
1213
// is orthogonal to the protocol and transport used, which is negotiated over stdout.
1314
type Runner interface {
14-
// Start should start the plugin and ensure any context required for servicing
15-
// other interface methods is set up.
16-
Start() error
15+
// Start should start the plugin and ensure any work required for servicing
16+
// other interface methods is done. If the context is cancelled, it should
17+
// only abort any attempts to _start_ the plugin. Waiting and shutdown are
18+
// handled separately.
19+
Start(ctx context.Context) error
1720

1821
// Stdout is used to negotiate the go-plugin protocol.
1922
Stdout() io.ReadCloser
@@ -34,10 +37,10 @@ type Runner interface {
3437
type AttachedRunner interface {
3538
// Wait should wait until the plugin stops running, whether in response to
3639
// an out of band signal or in response to calling Kill().
37-
Wait() error
40+
Wait(ctx context.Context) error
3841

3942
// Kill should stop the plugin and perform any cleanup required.
40-
Kill() error
43+
Kill(ctx context.Context) error
4144

4245
// ID is a unique identifier to represent the running plugin. e.g. pid or
4346
// container ID.

0 commit comments

Comments
 (0)