- Runtime: ghost containers can be killed.

This commit is contained in:
Solomon Hykes 2013-04-22 22:30:33 -07:00
commit 95e066d24f
3 changed files with 47 additions and 17 deletions

View File

@ -836,6 +836,10 @@ func (srv *Server) CmdAttach(stdin io.ReadCloser, stdout rcli.DockerConn, args .
return fmt.Errorf("No such container: %s", name) 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 { if container.Config.Tty {
stdout.SetOptionRawTerminal() stdout.SetOptionRawTerminal()
} }

View File

@ -530,16 +530,42 @@ func (container *Container) releaseNetwork() {
container.NetworkSettings = &NetworkSettings{} 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() { func (container *Container) monitor() {
// Wait for the program to exit // Wait for the program to exit
Debugf("Waiting for process") Debugf("Waiting for process")
// 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 { if err := container.cmd.Wait(); err != nil {
// Discard the error as any signals or non 0 returns will generate an error // Discard the error as any signals or non 0 returns will generate an error
Debugf("%s: Process: %s", container.Id, err) Debugf("%s: Process: %s", container.Id, err)
} }
}
Debugf("Process finished") 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 // Cleanup
container.releaseNetwork() container.releaseNetwork()
@ -588,7 +614,7 @@ func (container *Container) monitor() {
} }
func (container *Container) kill() error { func (container *Container) kill() error {
if !container.State.Running || container.cmd == nil { if !container.State.Running {
return nil return nil
} }
@ -600,6 +626,9 @@ func (container *Container) kill() error {
// 2. Wait for the process to die, in last resort, try to kill the process directly // 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 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) 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 { if err := container.cmd.Process.Kill(); err != nil {
return err return err
@ -617,9 +646,6 @@ func (container *Container) Kill() error {
if !container.State.Running { if !container.State.Running {
return nil return nil
} }
if container.State.Ghost {
return fmt.Errorf("Can't kill ghost container")
}
return container.kill() return container.kill()
} }
@ -629,9 +655,6 @@ func (container *Container) Stop(seconds int) error {
if !container.State.Running { if !container.State.Running {
return nil return nil
} }
if container.State.Ghost {
return fmt.Errorf("Can't stop ghost container")
}
// 1. Send a SIGTERM // 1. Send a SIGTERM
if output, err := exec.Command("lxc-kill", "-n", container.Id, "15").CombinedOutput(); err != nil { if output, err := exec.Command("lxc-kill", "-n", container.Id, "15").CombinedOutput(); err != nil {

View File

@ -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) // Even if not running, we init the lock (prevents races in start/stop/kill)
container.State.initLock() container.State.initLock()
@ -207,6 +201,15 @@ func (runtime *Runtime) Register(container *Container) error {
// done // done
runtime.containers.PushBack(container) runtime.containers.PushBack(container)
runtime.idIndex.Add(container.Id) 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 return nil
} }