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  }