func MakeContainer(run ds.Run) (_ Container, err error) { if dkr == "" { return nil, errors.New("docker not enabled on this server") } ch := make(chan error, 1) con := &container{ name: "via-circuit-" + lang.ChooseReceiverID().String()[1:], exit: ch, } con.cmd = exec.Command(dkr, run.Arg(con.name)...) con.cmd.Stdin, con.stdin = interruptible.BufferPipe(StdBufferLen) con.stdout, con.cmd.Stdout = interruptible.BufferPipe(StdBufferLen) con.stderr, con.cmd.Stderr = interruptible.BufferPipe(StdBufferLen) if err = con.cmd.Start(); err != nil { return nil, err } go func() { ch <- con.cmd.Wait() close(ch) con.cmd.Stdout.(io.Closer).Close() con.cmd.Stderr.(io.Closer).Close() }() runtime.SetFinalizer(con, func(c *container) { exec.Command(dkr, "rm", c.name).Run() }, ) return con, nil }
func MakeProc(cmd Cmd) Proc { p := &proc{} // std* p.cmd.cmd.Stdin, p.stdin = interruptible.BufferPipe(32e3) p.stdout, p.cmd.cmd.Stdout = interruptible.BufferPipe(32e3) p.stderr, p.cmd.cmd.Stderr = interruptible.BufferPipe(32e3) // exit ch, abr := make(chan error, 1), make(chan struct{}) p.cmd.wait, p.wait = ch, ch p.abr, p.cmd.abr = abr, abr // cmd p.cmd.cmd.Env = cmd.Env bin := strings.TrimSpace(cmd.Path) p.cmd.cmd.Path = bin p.cmd.cmd.Args = append([]string{bin}, cmd.Args...) p.cmd.scrb = cmd.Scrub // exec if err := p.cmd.cmd.Start(); err != nil { p.cmd.wait <- fmt.Errorf("exec error: %s", err.Error()) close(p.cmd.wait) return p } go func() { p.cmd.wait <- p.cmd.cmd.Wait() close(p.cmd.wait) p.cmd.cmd.Stdout.(io.Closer).Close() p.cmd.cmd.Stderr.(io.Closer).Close() }() return p }
// Send … // The returned WriteCloser must be closed at finalization. func (v *valve) Send() (io.WriteCloser, error) { v.send.Lock() defer v.send.Unlock() if v.send.tun == nil { return nil, errors.New("channel closed") } r, w := interruptible.BufferPipe(32e3) select { case v.send.tun <- r: v.incSend() return w, nil case <-v.send.abr: return nil, errors.New("channel aborted") } }