зеркало из https://github.com/microsoft/docker.git
Fix an issue where already allocated ports would not trigger an error.
Docker-DCO-1.1-Signed-off-by: Erik Hollensbe <github@hollensbe.org> (github: erikh)
This commit is contained in:
Родитель
3109fc9537
Коммит
3b6a29b81a
|
@ -100,11 +100,28 @@ func Map(container net.Addr, hostIP net.IP, hostPort int) (host net.Addr, err er
|
||||||
m.userlandProxy = proxy
|
m.userlandProxy = proxy
|
||||||
currentMappings[key] = m
|
currentMappings[key] = m
|
||||||
|
|
||||||
if err := proxy.Start(); err != nil {
|
cleanup := func() error {
|
||||||
// need to undo the iptables rules before we return
|
// need to undo the iptables rules before we return
|
||||||
forward(iptables.Delete, m.proto, hostIP, allocatedHostPort, containerIP.String(), containerPort)
|
forward(iptables.Delete, m.proto, hostIP, allocatedHostPort, containerIP.String(), containerPort)
|
||||||
|
proxy.Stop()
|
||||||
|
forward(iptables.Delete, m.proto, hostIP, allocatedHostPort, containerIP.String(), containerPort)
|
||||||
|
m.userlandProxy = nil
|
||||||
|
delete(currentMappings, key)
|
||||||
|
if err := portallocator.ReleasePort(hostIP, m.proto, allocatedHostPort); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil, err
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := proxy.Start(); err != nil {
|
||||||
|
if err := cleanup(); err != nil {
|
||||||
|
return nil, fmt.Errorf("Error during port allocation cleanup: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err == ErrPortMappingFailure {
|
||||||
|
return nil, portallocator.NewErrPortAlreadyAllocated(hostIP.String(), allocatedHostPort)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return m.host, nil
|
return m.host, nil
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package portmapper
|
package portmapper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
|
@ -9,11 +10,14 @@ import (
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"strconv"
|
"strconv"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/docker/docker/pkg/proxy"
|
"github.com/docker/docker/pkg/proxy"
|
||||||
"github.com/docker/docker/reexec"
|
"github.com/docker/docker/reexec"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var ErrPortMappingFailure = errors.New("Failure Mapping Port")
|
||||||
|
|
||||||
const userlandProxyCommandName = "docker-proxy"
|
const userlandProxyCommandName = "docker-proxy"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -37,9 +41,12 @@ func execProxy() {
|
||||||
|
|
||||||
p, err := proxy.NewProxy(host, container)
|
p, err := proxy.NewProxy(host, container)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
os.Stdout.WriteString("1\n")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
os.Stdout.WriteString("0\n")
|
||||||
|
|
||||||
go handleStopSignals(p)
|
go handleStopSignals(p)
|
||||||
|
|
||||||
// Run will block until the proxy stops
|
// Run will block until the proxy stops
|
||||||
|
@ -96,10 +103,8 @@ func NewProxyCommand(proto string, hostIP net.IP, hostPort int, containerIP net.
|
||||||
|
|
||||||
return &proxyCommand{
|
return &proxyCommand{
|
||||||
cmd: &exec.Cmd{
|
cmd: &exec.Cmd{
|
||||||
Path: reexec.Self(),
|
Path: reexec.Self(),
|
||||||
Args: args,
|
Args: args,
|
||||||
Stdout: os.Stdout,
|
|
||||||
Stderr: os.Stderr,
|
|
||||||
SysProcAttr: &syscall.SysProcAttr{
|
SysProcAttr: &syscall.SysProcAttr{
|
||||||
Pdeathsig: syscall.SIGTERM, // send a sigterm to the proxy if the daemon process dies
|
Pdeathsig: syscall.SIGTERM, // send a sigterm to the proxy if the daemon process dies
|
||||||
},
|
},
|
||||||
|
@ -108,12 +113,44 @@ func NewProxyCommand(proto string, hostIP net.IP, hostPort int, containerIP net.
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *proxyCommand) Start() error {
|
func (p *proxyCommand) Start() error {
|
||||||
return p.cmd.Start()
|
stdout, err := p.cmd.StdoutPipe()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := p.cmd.Start(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
errchan := make(chan error)
|
||||||
|
after := time.After(1 * time.Second)
|
||||||
|
go func() {
|
||||||
|
buf := make([]byte, 2)
|
||||||
|
stdout.Read(buf)
|
||||||
|
|
||||||
|
if string(buf) != "0\n" {
|
||||||
|
errchan <- ErrPortMappingFailure
|
||||||
|
} else {
|
||||||
|
errchan <- nil
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
var readErr error
|
||||||
|
|
||||||
|
select {
|
||||||
|
case readErr = <-errchan:
|
||||||
|
case <-after:
|
||||||
|
readErr = ErrPortMappingFailure
|
||||||
|
}
|
||||||
|
|
||||||
|
return readErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *proxyCommand) Stop() error {
|
func (p *proxyCommand) Stop() error {
|
||||||
err := p.cmd.Process.Signal(os.Interrupt)
|
if p.cmd.Process != nil {
|
||||||
p.cmd.Wait()
|
err := p.cmd.Process.Signal(os.Interrupt)
|
||||||
|
p.cmd.Wait()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return err
|
return nil
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче