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 }