func (s *GardenServer) streamInput(decoder *json.Decoder, in *io.PipeWriter, process garden.Process, connCloseCh chan struct{}) {
	for {
		var payload transport.ProcessPayload
		err := decoder.Decode(&payload)
		if err != nil {
			close(connCloseCh)
			in.CloseWithError(errors.New("Connection closed"))
			return
		}

		switch {
		case payload.TTY != nil:
			process.SetTTY(*payload.TTY)

		case payload.Source != nil:
			if payload.Data == nil {
				in.Close()
				return
			} else {
				_, err := in.Write([]byte(*payload.Data))
				if err != nil {
					return
				}
			}

		case payload.Signal != nil:
			s.logger.Info("stream-input-process-signal", lager.Data{"payload": payload})

			switch *payload.Signal {
			case garden.SignalKill:
				err = process.Signal(garden.SignalKill)
				if err != nil {
					s.logger.Error("stream-input-process-signal-kill-failed", err, lager.Data{"payload": payload})
				}
			case garden.SignalTerminate:
				err = process.Signal(garden.SignalTerminate)
				if err != nil {
					s.logger.Error("stream-input-process-signal-terminate-failed", err, lager.Data{"payload": payload})
				}
			default:
				s.logger.Error("stream-input-unknown-process-payload-signal", nil, lager.Data{"payload": payload})
				in.Close()
				return
			}

		default:
			s.logger.Error("stream-input-unknown-process-payload", nil, lager.Data{"payload": payload})
			in.Close()
			return
		}
	}
}
	AfterEach(func() {
		Expect(client.DestroyAndStop()).To(Succeed())
	})

	const (
		subnetName string = "177-100-10-0"
	)

	Context("when a container is created and then garden is restarted", func() {
		var (
			container        garden.Container
			hostNetInPort    uint32
			externalIP       string
			interfacePrefix  string
			propertiesDir    string
			existingProc     garden.Process
			containerSpec    garden.ContainerSpec
			restartArgs      []string
			gracefulShutdown bool
		)

		BeforeEach(func() {
			var err error
			propertiesDir, err = ioutil.TempDir("", "props")
			Expect(err).NotTo(HaveOccurred())
			args = append(args, "--properties-path", path.Join(propertiesDir, "props.json"))

			containerSpec = garden.ContainerSpec{
				Network: "177.100.10.30/30",
			}
					Stdout: io.MultiWriter(GinkgoWriter, stdout),
					Stderr: GinkgoWriter,
				})
				Expect(err).ToNot(HaveOccurred())
				Eventually(stdout).Should(gbytes.Say("waiting"))

				Expect(process.Signal(garden.SignalTerminate)).To(Succeed())
				Expect(process.Wait()).NotTo(BeZero())

				checkProcessIsGone(container, "sh -c while")

				close(done)
			}, 10.0)

			Context("when killing a process that does not use streaming", func() {
				var process garden.Process
				var buff *gbytes.Buffer

				JustBeforeEach(func() {
					var err error

					buff = gbytes.NewBuffer()
					process, err = container.Run(garden.ProcessSpec{
						User: "******",
						Path: "sh",
						Args: []string{
							"-c", "while true; do echo stillhere; sleep 1; done",
						},
					}, garden.ProcessIO{Stdout: buff})
					Expect(err).ToNot(HaveOccurred())
func (s *GardenServer) streamProcess(logger lager.Logger, conn net.Conn, process garden.Process, stdinPipe *io.PipeWriter, connCloseCh chan struct{}) {
	statusCh := make(chan int, 1)
	errCh := make(chan error, 1)

	go func() {
		status, err := process.Wait()
		if err != nil {
			logger.Error("wait-failed", err, lager.Data{
				"id": process.ID(),
			})

			errCh <- err
		} else {
			logger.Info("exited", lager.Data{
				"status": status,
				"id":     process.ID(),
			})

			statusCh <- status
		}
	}()

	for {
		select {

		case status := <-statusCh:
			transport.WriteMessage(conn, &transport.ProcessPayload{
				ProcessID:  process.ID(),
				ExitStatus: &status,
			})

			stdinPipe.Close()
			return

		case err := <-errCh:
			e := err.Error()
			transport.WriteMessage(conn, &transport.ProcessPayload{
				ProcessID: process.ID(),
				Error:     &e,
			})

			stdinPipe.Close()
			return

		case <-s.stopping:
			logger.Debug("detaching", lager.Data{
				"id": process.ID(),
			})

			return

		case <-connCloseCh:

			return
		}
	}
}