github.com/schwarzm/garden-linux@v0.0.0-20150507151835-33bca2147c47/linux_backend/namespaced_signaller.go (about)

     1  package linux_backend
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"os"
     7  	"os/exec"
     8  	"path/filepath"
     9  
    10  	"time"
    11  
    12  	"github.com/cloudfoundry/gunk/command_runner"
    13  )
    14  
    15  // Kills a process by invoking ./bin/wsh in the given container path using
    16  // a PID read from the given pidFile
    17  type NamespacedSignaller struct {
    18  	Runner        command_runner.CommandRunner
    19  	ContainerPath string
    20  	PidFilePath   string
    21  }
    22  
    23  func (n *NamespacedSignaller) Signal(signal os.Signal) error {
    24  	pid, err := pidFromFile(n.PidFilePath)
    25  	if err != nil {
    26  		return err
    27  	}
    28  
    29  	return n.Runner.Run(exec.Command(filepath.Join(n.ContainerPath, "bin/wsh"),
    30  		"--socket", filepath.Join(n.ContainerPath, "run/wshd.sock"),
    31  		"kill", fmt.Sprintf("-%d", signal), fmt.Sprintf("%d", pid)))
    32  }
    33  
    34  func pidFromFile(pidFilePath string) (int, error) {
    35  	pidFile, err := openPIDFile(pidFilePath)
    36  	if err != nil {
    37  		return 0, err
    38  	}
    39  	defer pidFile.Close()
    40  
    41  	fileContent, err := readPIDFile(pidFile)
    42  	if err != nil {
    43  		return 0, err
    44  	}
    45  
    46  	var pid int
    47  	_, err = fmt.Sscanf(fileContent, "%d", &pid)
    48  	if err != nil {
    49  		return 0, fmt.Errorf("linux_backend: can't parse PID file content: %v", err)
    50  	}
    51  
    52  	return pid, nil
    53  }
    54  
    55  func openPIDFile(pidFilePath string) (*os.File, error) {
    56  	var err error
    57  
    58  	for i := 0; i < 100; i++ { // 10 seconds
    59  		var pidFile *os.File
    60  		pidFile, err = os.Open(pidFilePath)
    61  		if err == nil {
    62  			return pidFile, nil
    63  		}
    64  		time.Sleep(time.Millisecond * 100)
    65  	}
    66  
    67  	return nil, fmt.Errorf("linux_backend: can't open PID file: %s", err)
    68  }
    69  
    70  func readPIDFile(pidFile *os.File) (string, error) {
    71  	var bytesReadAmt int
    72  
    73  	buffer := make([]byte, 32)
    74  	for i := 0; i < 100; i++ { // retry 10 seconds
    75  		bytesReadAmt, _ = pidFile.Read(buffer)
    76  
    77  		if bytesReadAmt == 0 {
    78  			pidFile.Seek(0, 0)
    79  			time.Sleep(time.Millisecond * 100)
    80  			continue
    81  		}
    82  		break
    83  	}
    84  
    85  	if bytesReadAmt == 0 {
    86  		return "", errors.New("linux_backend: can't read PID file: is empty or non existent")
    87  	}
    88  
    89  	return string(buffer), nil
    90  }