From 82848d415866d08121bb52857e7d7b1d2a952c0c Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Fri, 19 Apr 2013 12:08:43 -0700 Subject: [PATCH 1/4] Allow to wait on container even after docker server restarts using lxc-info --- container.go | 34 ++++++++++++++++++++++++++++++---- runtime.go | 15 +++++++++------ 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/container.go b/container.go index c2c6fddd40..91c5806ecb 100644 --- a/container.go +++ b/container.go @@ -530,16 +530,42 @@ func (container *Container) releaseNetwork() { container.NetworkSettings = &NetworkSettings{} } +// FIXME: replace this with a control socket within docker-init +func (container *Container) waitLxc() error { + for { + if output, err := exec.Command("lxc-info", "-n", container.Id).CombinedOutput(); err != nil { + return err + } else { + if !strings.Contains(string(output), "RUNNING") { + return nil + } + } + time.Sleep(500 * time.Millisecond) + } + return nil +} + func (container *Container) monitor() { // Wait for the program to exit Debugf("Waiting for process") - if err := container.cmd.Wait(); err != nil { - // Discard the error as any signals or non 0 returns will generate an error - Debugf("%s: Process: %s", container.Id, err) + + // If the command does not exists, try to wait via lxc + if container.cmd == nil { + if err := container.waitLxc(); err != nil { + Debugf("%s: Process: %s", container.Id, err) + } + } else { + if err := container.cmd.Wait(); err != nil { + // Discard the error as any signals or non 0 returns will generate an error + Debugf("%s: Process: %s", container.Id, err) + } } Debugf("Process finished") - exitCode := container.cmd.ProcessState.Sys().(syscall.WaitStatus).ExitStatus() + var exitCode int = -1 + if container.cmd != nil { + exitCode = container.cmd.ProcessState.Sys().(syscall.WaitStatus).ExitStatus() + } // Cleanup container.releaseNetwork() diff --git a/runtime.go b/runtime.go index b894a2cdaf..1b4fceced7 100644 --- a/runtime.go +++ b/runtime.go @@ -184,12 +184,6 @@ func (runtime *Runtime) Register(container *Container) error { } } - // If the container is not running or just has been flagged not running - // then close the wait lock chan (will be reset upon start) - if !container.State.Running { - close(container.waitLock) - } - // Even if not running, we init the lock (prevents races in start/stop/kill) container.State.initLock() @@ -207,6 +201,15 @@ func (runtime *Runtime) Register(container *Container) error { // done runtime.containers.PushBack(container) runtime.idIndex.Add(container.Id) + + // If the container is not running or just has been flagged not running + // then close the wait lock chan (will be reset upon start) + if !container.State.Running { + close(container.waitLock) + } else { + container.allocateNetwork() + go container.monitor() + } return nil } From d440782e17d384d52c813f93cd53d2d8a15fd13a Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Fri, 19 Apr 2013 12:12:30 -0700 Subject: [PATCH 2/4] Allow to kill container after docker server restarts --- container.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/container.go b/container.go index 91c5806ecb..1f60e08a9d 100644 --- a/container.go +++ b/container.go @@ -614,7 +614,7 @@ func (container *Container) monitor() { } func (container *Container) kill() error { - if !container.State.Running || container.cmd == nil { + if !container.State.Running { return nil } @@ -626,6 +626,9 @@ func (container *Container) kill() error { // 2. Wait for the process to die, in last resort, try to kill the process directly if err := container.WaitTimeout(10 * time.Second); err != nil { + if container.cmd == nil { + return fmt.Errorf("lxc-kill failed, impossible to kill the container %s", container.Id) + } log.Printf("Container %s failed to exit within 10 seconds of lxc SIGKILL - trying direct SIGKILL", container.Id) if err := container.cmd.Process.Kill(); err != nil { return err From f926ed182f908aba20980202becfcdbe2d1e9c34 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Fri, 19 Apr 2013 12:21:39 -0700 Subject: [PATCH 3/4] Allow to kill/stop ghosts --- container.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/container.go b/container.go index 1f60e08a9d..bac0951da4 100644 --- a/container.go +++ b/container.go @@ -646,9 +646,6 @@ func (container *Container) Kill() error { if !container.State.Running { return nil } - if container.State.Ghost { - return fmt.Errorf("Can't kill ghost container") - } return container.kill() } @@ -658,9 +655,6 @@ func (container *Container) Stop(seconds int) error { if !container.State.Running { return nil } - if container.State.Ghost { - return fmt.Errorf("Can't stop ghost container") - } // 1. Send a SIGTERM if output, err := exec.Command("lxc-kill", "-n", container.Id, "15").CombinedOutput(); err != nil { From b76d63cb0c97aacec6d81c07108d2a573fb8af05 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Fri, 19 Apr 2013 14:18:03 -0700 Subject: [PATCH 4/4] Forbid attach to ghost --- commands.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/commands.go b/commands.go index b0440a9766..de814d6648 100644 --- a/commands.go +++ b/commands.go @@ -836,6 +836,10 @@ func (srv *Server) CmdAttach(stdin io.ReadCloser, stdout rcli.DockerConn, args . return fmt.Errorf("No such container: %s", name) } + if container.State.Ghost { + return fmt.Errorf("Impossible to attach to a ghost container") + } + if container.Config.Tty { stdout.SetOptionRawTerminal() }