... | ... |
@@ -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 |
|