| ... | ... |
@@ -95,6 +95,11 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba |
| 95 | 95 |
if err != nil {
|
| 96 | 96 |
return -1, err |
| 97 | 97 |
} |
| 98 |
+ |
|
| 99 |
+ if err := execdriver.SetTerminal(c, pipes); err != nil {
|
|
| 100 |
+ return -1, err |
|
| 101 |
+ } |
|
| 102 |
+ |
|
| 98 | 103 |
d.Lock() |
| 99 | 104 |
d.activeContainers[c.ID] = &activeContainer{
|
| 100 | 105 |
container: container, |
| ... | ... |
@@ -106,6 +111,7 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba |
| 106 | 106 |
dataPath = filepath.Join(d.root, c.ID) |
| 107 | 107 |
args = append([]string{c.Entrypoint}, c.Arguments...)
|
| 108 | 108 |
) |
| 109 |
+ |
|
| 109 | 110 |
if err := d.createContainerRoot(c.ID); err != nil {
|
| 110 | 111 |
return -1, err |
| 111 | 112 |
} |
| ... | ... |
@@ -115,9 +121,7 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba |
| 115 | 115 |
return -1, err |
| 116 | 116 |
} |
| 117 | 117 |
|
| 118 |
- term := getTerminal(c, pipes) |
|
| 119 |
- |
|
| 120 |
- return namespaces.Exec(container, term, c.Rootfs, dataPath, args, func(container *libcontainer.Config, console, rootfs, dataPath, init string, child *os.File, args []string) *exec.Cmd {
|
|
| 118 |
+ return namespaces.Exec(container, c.Stdin, c.Stdout, c.Stderr, c.Console, c.Rootfs, dataPath, args, func(container *libcontainer.Config, console, rootfs, dataPath, init string, child *os.File, args []string) *exec.Cmd {
|
|
| 121 | 119 |
// we need to join the rootfs because namespaces will setup the rootfs and chroot |
| 122 | 120 |
initPath := filepath.Join(c.Rootfs, c.InitPath) |
| 123 | 121 |
|
| ... | ... |
@@ -201,11 +205,13 @@ func (d *driver) Terminate(p *execdriver.Command) error {
|
| 201 | 201 |
if err != nil {
|
| 202 | 202 |
return err |
| 203 | 203 |
} |
| 204 |
+ |
|
| 204 | 205 |
if state.InitStartTime == currentStartTime {
|
| 205 | 206 |
err = syscall.Kill(p.Process.Pid, 9) |
| 206 | 207 |
syscall.Wait4(p.Process.Pid, nil, 0, nil) |
| 207 | 208 |
} |
| 208 | 209 |
d.removeContainerRoot(p.ID) |
| 210 |
+ |
|
| 209 | 211 |
return err |
| 210 | 212 |
|
| 211 | 213 |
} |
| ... | ... |
@@ -266,18 +272,3 @@ func getEnv(key string, env []string) string {
|
| 266 | 266 |
} |
| 267 | 267 |
return "" |
| 268 | 268 |
} |
| 269 |
- |
|
| 270 |
-func getTerminal(c *execdriver.Command, pipes *execdriver.Pipes) namespaces.Terminal {
|
|
| 271 |
- var term namespaces.Terminal |
|
| 272 |
- if c.Tty {
|
|
| 273 |
- term = &dockerTtyTerm{
|
|
| 274 |
- pipes: pipes, |
|
| 275 |
- } |
|
| 276 |
- } else {
|
|
| 277 |
- term = &dockerStdTerm{
|
|
| 278 |
- pipes: pipes, |
|
| 279 |
- } |
|
| 280 |
- } |
|
| 281 |
- c.Terminal = term |
|
| 282 |
- return term |
|
| 283 |
-} |
| 284 | 269 |
deleted file mode 100644 |
| ... | ... |
@@ -1,42 +0,0 @@ |
| 1 |
-/* |
|
| 2 |
- These types are wrappers around the libcontainer Terminal interface so that |
|
| 3 |
- we can resuse the docker implementations where possible. |
|
| 4 |
-*/ |
|
| 5 |
-package native |
|
| 6 |
- |
|
| 7 |
-import ( |
|
| 8 |
- "github.com/dotcloud/docker/daemon/execdriver" |
|
| 9 |
- "io" |
|
| 10 |
- "os" |
|
| 11 |
- "os/exec" |
|
| 12 |
-) |
|
| 13 |
- |
|
| 14 |
-type dockerStdTerm struct {
|
|
| 15 |
- execdriver.StdConsole |
|
| 16 |
- pipes *execdriver.Pipes |
|
| 17 |
-} |
|
| 18 |
- |
|
| 19 |
-func (d *dockerStdTerm) Attach(cmd *exec.Cmd) error {
|
|
| 20 |
- return d.AttachPipes(cmd, d.pipes) |
|
| 21 |
-} |
|
| 22 |
- |
|
| 23 |
-func (d *dockerStdTerm) SetMaster(master *os.File) {
|
|
| 24 |
- // do nothing |
|
| 25 |
-} |
|
| 26 |
- |
|
| 27 |
-type dockerTtyTerm struct {
|
|
| 28 |
- execdriver.TtyConsole |
|
| 29 |
- pipes *execdriver.Pipes |
|
| 30 |
-} |
|
| 31 |
- |
|
| 32 |
-func (t *dockerTtyTerm) Attach(cmd *exec.Cmd) error {
|
|
| 33 |
- go io.Copy(t.pipes.Stdout, t.MasterPty) |
|
| 34 |
- if t.pipes.Stdin != nil {
|
|
| 35 |
- go io.Copy(t.MasterPty, t.pipes.Stdin) |
|
| 36 |
- } |
|
| 37 |
- return nil |
|
| 38 |
-} |
|
| 39 |
- |
|
| 40 |
-func (t *dockerTtyTerm) SetMaster(master *os.File) {
|
|
| 41 |
- t.MasterPty = master |
|
| 42 |
-} |
| ... | ... |
@@ -1,11 +1,12 @@ |
| 1 | 1 |
package execdriver |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
- "github.com/dotcloud/docker/pkg/term" |
|
| 5 |
- "github.com/kr/pty" |
|
| 6 | 4 |
"io" |
| 7 | 5 |
"os" |
| 8 | 6 |
"os/exec" |
| 7 |
+ |
|
| 8 |
+ "github.com/dotcloud/docker/pkg/system" |
|
| 9 |
+ "github.com/dotcloud/docker/pkg/term" |
|
| 9 | 10 |
) |
| 10 | 11 |
|
| 11 | 12 |
func SetTerminal(command *Command, pipes *Pipes) error {
|
| ... | ... |
@@ -13,37 +14,42 @@ func SetTerminal(command *Command, pipes *Pipes) error {
|
| 13 | 13 |
term Terminal |
| 14 | 14 |
err error |
| 15 | 15 |
) |
| 16 |
+ |
|
| 16 | 17 |
if command.Tty {
|
| 17 | 18 |
term, err = NewTtyConsole(command, pipes) |
| 18 | 19 |
} else {
|
| 19 | 20 |
term, err = NewStdConsole(command, pipes) |
| 20 | 21 |
} |
| 22 |
+ |
|
| 21 | 23 |
if err != nil {
|
| 22 | 24 |
return err |
| 23 | 25 |
} |
| 26 |
+ |
|
| 24 | 27 |
command.Terminal = term |
| 28 |
+ |
|
| 25 | 29 |
return nil |
| 26 | 30 |
} |
| 27 | 31 |
|
| 28 | 32 |
type TtyConsole struct {
|
| 29 | 33 |
MasterPty *os.File |
| 30 |
- SlavePty *os.File |
|
| 31 | 34 |
} |
| 32 | 35 |
|
| 33 | 36 |
func NewTtyConsole(command *Command, pipes *Pipes) (*TtyConsole, error) {
|
| 34 |
- ptyMaster, ptySlave, err := pty.Open() |
|
| 37 |
+ ptyMaster, console, err := system.CreateMasterAndConsole() |
|
| 35 | 38 |
if err != nil {
|
| 36 | 39 |
return nil, err |
| 37 | 40 |
} |
| 41 |
+ |
|
| 38 | 42 |
tty := &TtyConsole{
|
| 39 | 43 |
MasterPty: ptyMaster, |
| 40 |
- SlavePty: ptySlave, |
|
| 41 | 44 |
} |
| 45 |
+ |
|
| 42 | 46 |
if err := tty.AttachPipes(&command.Cmd, pipes); err != nil {
|
| 43 | 47 |
tty.Close() |
| 44 | 48 |
return nil, err |
| 45 | 49 |
} |
| 46 |
- command.Console = tty.SlavePty.Name() |
|
| 50 |
+ command.Console = console |
|
| 51 |
+ |
|
| 47 | 52 |
return tty, nil |
| 48 | 53 |
} |
| 49 | 54 |
|
| ... | ... |
@@ -56,9 +62,6 @@ func (t *TtyConsole) Resize(h, w int) error {
|
| 56 | 56 |
} |
| 57 | 57 |
|
| 58 | 58 |
func (t *TtyConsole) AttachPipes(command *exec.Cmd, pipes *Pipes) error {
|
| 59 |
- command.Stdout = t.SlavePty |
|
| 60 |
- command.Stderr = t.SlavePty |
|
| 61 |
- |
|
| 62 | 59 |
go func() {
|
| 63 | 60 |
if wb, ok := pipes.Stdout.(interface {
|
| 64 | 61 |
CloseWriters() error |
| ... | ... |
@@ -69,19 +72,16 @@ func (t *TtyConsole) AttachPipes(command *exec.Cmd, pipes *Pipes) error {
|
| 69 | 69 |
}() |
| 70 | 70 |
|
| 71 | 71 |
if pipes.Stdin != nil {
|
| 72 |
- command.Stdin = t.SlavePty |
|
| 73 |
- command.SysProcAttr.Setctty = true |
|
| 74 |
- |
|
| 75 | 72 |
go func() {
|
| 76 | 73 |
defer pipes.Stdin.Close() |
| 77 | 74 |
io.Copy(t.MasterPty, pipes.Stdin) |
| 78 | 75 |
}() |
| 79 | 76 |
} |
| 77 |
+ |
|
| 80 | 78 |
return nil |
| 81 | 79 |
} |
| 82 | 80 |
|
| 83 | 81 |
func (t *TtyConsole) Close() error {
|
| 84 |
- t.SlavePty.Close() |
|
| 85 | 82 |
return t.MasterPty.Close() |
| 86 | 83 |
} |
| 87 | 84 |
|