github.com/hashicorp/go-plugin@v1.6.0/internal/cmdrunner/cmd_reattach.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package cmdrunner 5 6 import ( 7 "context" 8 "fmt" 9 "net" 10 "os" 11 12 "github.com/hashicorp/go-plugin/runner" 13 ) 14 15 // ReattachFunc returns a function that allows reattaching to a plugin running 16 // as a plain process. The process may or may not be a child process. 17 func ReattachFunc(pid int, addr net.Addr) runner.ReattachFunc { 18 return func() (runner.AttachedRunner, error) { 19 p, err := os.FindProcess(pid) 20 if err != nil { 21 // On Unix systems, FindProcess never returns an error. 22 // On Windows, for non-existent pids it returns: 23 // os.SyscallError - 'OpenProcess: the paremter is incorrect' 24 return nil, ErrProcessNotFound 25 } 26 27 // Attempt to connect to the addr since on Unix systems FindProcess 28 // doesn't actually return an error if it can't find the process. 29 conn, err := net.Dial(addr.Network(), addr.String()) 30 if err != nil { 31 p.Kill() 32 return nil, ErrProcessNotFound 33 } 34 conn.Close() 35 36 return &CmdAttachedRunner{ 37 pid: pid, 38 process: p, 39 }, nil 40 } 41 } 42 43 // CmdAttachedRunner is mostly a subset of CmdRunner, except the Wait function 44 // does not assume the process is a child of the host process, and so uses a 45 // different implementation to wait on the process. 46 type CmdAttachedRunner struct { 47 pid int 48 process *os.Process 49 50 addrTranslator 51 } 52 53 func (c *CmdAttachedRunner) Wait(_ context.Context) error { 54 return pidWait(c.pid) 55 } 56 57 func (c *CmdAttachedRunner) Kill(_ context.Context) error { 58 return c.process.Kill() 59 } 60 61 func (c *CmdAttachedRunner) ID() string { 62 return fmt.Sprintf("%d", c.pid) 63 }