| ... | ... |
@@ -836,6 +836,10 @@ func (srv *Server) CmdAttach(stdin io.ReadCloser, stdout rcli.DockerConn, args . |
| 836 | 836 |
return fmt.Errorf("No such container: %s", name)
|
| 837 | 837 |
} |
| 838 | 838 |
|
| 839 |
+ if container.State.Ghost {
|
|
| 840 |
+ return fmt.Errorf("Impossible to attach to a ghost container")
|
|
| 841 |
+ } |
|
| 842 |
+ |
|
| 839 | 843 |
if container.Config.Tty {
|
| 840 | 844 |
stdout.SetOptionRawTerminal() |
| 841 | 845 |
} |
| ... | ... |
@@ -530,16 +530,42 @@ func (container *Container) releaseNetwork() {
|
| 530 | 530 |
container.NetworkSettings = &NetworkSettings{}
|
| 531 | 531 |
} |
| 532 | 532 |
|
| 533 |
+// FIXME: replace this with a control socket within docker-init |
|
| 534 |
+func (container *Container) waitLxc() error {
|
|
| 535 |
+ for {
|
|
| 536 |
+ if output, err := exec.Command("lxc-info", "-n", container.Id).CombinedOutput(); err != nil {
|
|
| 537 |
+ return err |
|
| 538 |
+ } else {
|
|
| 539 |
+ if !strings.Contains(string(output), "RUNNING") {
|
|
| 540 |
+ return nil |
|
| 541 |
+ } |
|
| 542 |
+ } |
|
| 543 |
+ time.Sleep(500 * time.Millisecond) |
|
| 544 |
+ } |
|
| 545 |
+ return nil |
|
| 546 |
+} |
|
| 547 |
+ |
|
| 533 | 548 |
func (container *Container) monitor() {
|
| 534 | 549 |
// Wait for the program to exit |
| 535 | 550 |
Debugf("Waiting for process")
|
| 536 |
- if err := container.cmd.Wait(); err != nil {
|
|
| 537 |
- // Discard the error as any signals or non 0 returns will generate an error |
|
| 538 |
- Debugf("%s: Process: %s", container.Id, err)
|
|
| 551 |
+ |
|
| 552 |
+ // If the command does not exists, try to wait via lxc |
|
| 553 |
+ if container.cmd == nil {
|
|
| 554 |
+ if err := container.waitLxc(); err != nil {
|
|
| 555 |
+ Debugf("%s: Process: %s", container.Id, err)
|
|
| 556 |
+ } |
|
| 557 |
+ } else {
|
|
| 558 |
+ if err := container.cmd.Wait(); err != nil {
|
|
| 559 |
+ // Discard the error as any signals or non 0 returns will generate an error |
|
| 560 |
+ Debugf("%s: Process: %s", container.Id, err)
|
|
| 561 |
+ } |
|
| 539 | 562 |
} |
| 540 | 563 |
Debugf("Process finished")
|
| 541 | 564 |
|
| 542 |
- exitCode := container.cmd.ProcessState.Sys().(syscall.WaitStatus).ExitStatus() |
|
| 565 |
+ var exitCode int = -1 |
|
| 566 |
+ if container.cmd != nil {
|
|
| 567 |
+ exitCode = container.cmd.ProcessState.Sys().(syscall.WaitStatus).ExitStatus() |
|
| 568 |
+ } |
|
| 543 | 569 |
|
| 544 | 570 |
// Cleanup |
| 545 | 571 |
container.releaseNetwork() |
| ... | ... |
@@ -588,7 +614,7 @@ func (container *Container) monitor() {
|
| 588 | 588 |
} |
| 589 | 589 |
|
| 590 | 590 |
func (container *Container) kill() error {
|
| 591 |
- if !container.State.Running || container.cmd == nil {
|
|
| 591 |
+ if !container.State.Running {
|
|
| 592 | 592 |
return nil |
| 593 | 593 |
} |
| 594 | 594 |
|
| ... | ... |
@@ -600,6 +626,9 @@ func (container *Container) kill() error {
|
| 600 | 600 |
|
| 601 | 601 |
// 2. Wait for the process to die, in last resort, try to kill the process directly |
| 602 | 602 |
if err := container.WaitTimeout(10 * time.Second); err != nil {
|
| 603 |
+ if container.cmd == nil {
|
|
| 604 |
+ return fmt.Errorf("lxc-kill failed, impossible to kill the container %s", container.Id)
|
|
| 605 |
+ } |
|
| 603 | 606 |
log.Printf("Container %s failed to exit within 10 seconds of lxc SIGKILL - trying direct SIGKILL", container.Id)
|
| 604 | 607 |
if err := container.cmd.Process.Kill(); err != nil {
|
| 605 | 608 |
return err |
| ... | ... |
@@ -617,9 +646,6 @@ func (container *Container) Kill() error {
|
| 617 | 617 |
if !container.State.Running {
|
| 618 | 618 |
return nil |
| 619 | 619 |
} |
| 620 |
- if container.State.Ghost {
|
|
| 621 |
- return fmt.Errorf("Can't kill ghost container")
|
|
| 622 |
- } |
|
| 623 | 620 |
return container.kill() |
| 624 | 621 |
} |
| 625 | 622 |
|
| ... | ... |
@@ -629,9 +655,6 @@ func (container *Container) Stop(seconds int) error {
|
| 629 | 629 |
if !container.State.Running {
|
| 630 | 630 |
return nil |
| 631 | 631 |
} |
| 632 |
- if container.State.Ghost {
|
|
| 633 |
- return fmt.Errorf("Can't stop ghost container")
|
|
| 634 |
- } |
|
| 635 | 632 |
|
| 636 | 633 |
// 1. Send a SIGTERM |
| 637 | 634 |
if output, err := exec.Command("lxc-kill", "-n", container.Id, "15").CombinedOutput(); err != nil {
|
| ... | ... |
@@ -184,12 +184,6 @@ func (runtime *Runtime) Register(container *Container) error {
|
| 184 | 184 |
} |
| 185 | 185 |
} |
| 186 | 186 |
|
| 187 |
- // If the container is not running or just has been flagged not running |
|
| 188 |
- // then close the wait lock chan (will be reset upon start) |
|
| 189 |
- if !container.State.Running {
|
|
| 190 |
- close(container.waitLock) |
|
| 191 |
- } |
|
| 192 |
- |
|
| 193 | 187 |
// Even if not running, we init the lock (prevents races in start/stop/kill) |
| 194 | 188 |
container.State.initLock() |
| 195 | 189 |
|
| ... | ... |
@@ -207,6 +201,15 @@ func (runtime *Runtime) Register(container *Container) error {
|
| 207 | 207 |
// done |
| 208 | 208 |
runtime.containers.PushBack(container) |
| 209 | 209 |
runtime.idIndex.Add(container.Id) |
| 210 |
+ |
|
| 211 |
+ // If the container is not running or just has been flagged not running |
|
| 212 |
+ // then close the wait lock chan (will be reset upon start) |
|
| 213 |
+ if !container.State.Running {
|
|
| 214 |
+ close(container.waitLock) |
|
| 215 |
+ } else {
|
|
| 216 |
+ container.allocateNetwork() |
|
| 217 |
+ go container.monitor() |
|
| 218 |
+ } |
|
| 210 | 219 |
return nil |
| 211 | 220 |
} |
| 212 | 221 |
|