diff options
| author | Felix Hanley <felix@userspace.com.au> | 2016-12-05 08:16:58 +0000 |
|---|---|---|
| committer | Felix Hanley <felix@userspace.com.au> | 2016-12-05 08:16:58 +0000 |
| commit | b049991a46a2f619344bd6e915745703864d0134 (patch) | |
| tree | ec1d3897a7b69c7c63a3774d4c42dfbb8cb46432 /vendor/github.com/zenazn/goji/bind/einhorn.go | |
| parent | e1c3d6f7db06d592538f1162b2b6b9f1b6efa330 (diff) | |
| download | go-dict2rest-master.tar.gz go-dict2rest-master.tar.bz2 | |
Diffstat (limited to 'vendor/github.com/zenazn/goji/bind/einhorn.go')
| -rw-r--r-- | vendor/github.com/zenazn/goji/bind/einhorn.go | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/vendor/github.com/zenazn/goji/bind/einhorn.go b/vendor/github.com/zenazn/goji/bind/einhorn.go new file mode 100644 index 0000000..e695c0e --- /dev/null +++ b/vendor/github.com/zenazn/goji/bind/einhorn.go @@ -0,0 +1,91 @@ +// +build !windows + +package bind + +import ( + "fmt" + "log" + "net" + "os" + "strconv" + "syscall" +) + +const tooBigErr = "bind: einhorn@%d not found (einhorn only passed %d fds)" +const bindErr = "bind: could not bind einhorn@%d: not running under einhorn" +const einhornErr = "bind: einhorn environment initialization error" +const ackErr = "bind: error ACKing to einhorn: %v" + +var einhornNumFds int + +func envInt(val string) (int, error) { + return strconv.Atoi(os.Getenv(val)) +} + +// Unfortunately this can't be a normal init function, because their execution +// order is undefined, and we need to run before the init() in bind.go. +func einhornInit() { + mpid, err := envInt("EINHORN_MASTER_PID") + if err != nil || mpid != os.Getppid() { + return + } + + einhornNumFds, err = envInt("EINHORN_FD_COUNT") + if err != nil { + einhornNumFds = 0 + return + } + + // Prevent einhorn's fds from leaking to our children + for i := 0; i < einhornNumFds; i++ { + syscall.CloseOnExec(einhornFdMap(i)) + } +} + +func usingEinhorn() bool { + return einhornNumFds > 0 +} + +func einhornFdMap(n int) int { + name := fmt.Sprintf("EINHORN_FD_%d", n) + fno, err := envInt(name) + if err != nil { + log.Fatal(einhornErr) + } + return fno +} + +func einhornBind(n int) (net.Listener, error) { + if !usingEinhorn() { + return nil, fmt.Errorf(bindErr, n) + } + if n >= einhornNumFds || n < 0 { + return nil, fmt.Errorf(tooBigErr, n, einhornNumFds) + } + + fno := einhornFdMap(n) + f := os.NewFile(uintptr(fno), fmt.Sprintf("einhorn@%d", n)) + defer f.Close() + return net.FileListener(f) +} + +// Fun story: this is actually YAML, not JSON. +const ackMsg = `{"command": "worker:ack", "pid": %d}` + "\n" + +func einhornAck() { + if !usingEinhorn() { + return + } + log.Print("bind: ACKing to einhorn") + + ctl, err := net.Dial("unix", os.Getenv("EINHORN_SOCK_PATH")) + if err != nil { + log.Fatalf(ackErr, err) + } + defer ctl.Close() + + _, err = fmt.Fprintf(ctl, ackMsg, os.Getpid()) + if err != nil { + log.Fatalf(ackErr, err) + } +} |
