Merge pull request #4831 from unclejack/final_bump_v0.9.1

Bump to version 0.9.1
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 40ba3d3..c8ea943 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,45 @@
 # Changelog
 
+## 0.9.1 (2014-03-24)
+
+#### Builder
+- Fix printing multiple messages on a single line. Fixes broken output during builds.
+
+#### Documentation
+- Fix external link on security of containers.
+
+#### Contrib
+- Fix init script cgroup mounting workarounds to be more similar to cgroupfs-mount and thus work properly.
+- Add variable for DOCKER_LOGFILE to sysvinit and use append instead of overwrite in opening the logfile.
+
+#### Hack
+- Generate md5 and sha256 hashes when building, and upload them via hack/release.sh.
+
+#### Remote API
+- Fix content-type detection in `docker cp`.
+
+#### Runtime
+- Use BSD raw mode on Darwin. Fixes nano, tmux and others.
+- Only unshare the mount namespace for execin.
+- Retry to retrieve the layer metadata up to 5 times for `docker pull`.
+- Merge existing config when committing.
+- Fix panic in monitor.
+- Disable daemon startup timeout.
+- Fix issue #4681: add loopback interface when networking is disabled.
+- Add failing test case for issue #4681.
+- Send SIGTERM to child, instead of SIGKILL.
+- Show the driver and the kernel version in `docker info` even when not in debug mode.
+- Always symlink /dev/ptmx for libcontainer. This fixes console related problems.
+- Fix issue caused by the absence of /etc/apparmor.d.
+- Don't leave empty cidFile behind when failing to create the container.
+- Improve deprecation message.
+- Fix attach exit on darwin.
+- devicemapper: improve handling of devicemapper devices (add per device lock, increase sleep time, unlock while sleeping).
+- devicemapper: succeed immediately when removing non-existing devices.
+- devicemapper: increase timeout in waitClose to 10 seconds.
+- Remove goroutine leak on error.
+- Update parseLxcInfo to comply with new lxc1.0 format.
+
 ## 0.9.0 (2014-03-10)
 
 #### Builder
diff --git a/VERSION b/VERSION
index ac39a10..f374f66 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.9.0
+0.9.1
diff --git a/api/client.go b/api/client.go
index 10075ae..d7d126e 100644
--- a/api/client.go
+++ b/api/client.go
@@ -13,6 +13,7 @@
 	"github.com/dotcloud/docker/engine"
 	"github.com/dotcloud/docker/nat"
 	flag "github.com/dotcloud/docker/pkg/mflag"
+	"github.com/dotcloud/docker/pkg/signal"
 	"github.com/dotcloud/docker/pkg/term"
 	"github.com/dotcloud/docker/registry"
 	"github.com/dotcloud/docker/runconfig"
@@ -24,11 +25,11 @@
 	"net/http/httputil"
 	"net/url"
 	"os"
-	"os/signal"
+	gosignal "os/signal"
 	"path"
 	"reflect"
 	"regexp"
-	"runtime"
+	goruntime "runtime"
 	"strconv"
 	"strings"
 	"syscall"
@@ -367,7 +368,7 @@
 	if dockerversion.VERSION != "" {
 		fmt.Fprintf(cli.out, "Client version: %s\n", dockerversion.VERSION)
 	}
-	fmt.Fprintf(cli.out, "Go version (client): %s\n", runtime.Version())
+	fmt.Fprintf(cli.out, "Go version (client): %s\n", goruntime.Version())
 	if dockerversion.GITCOMMIT != "" {
 		fmt.Fprintf(cli.out, "Git commit (client): %s\n", dockerversion.GITCOMMIT)
 	}
@@ -432,7 +433,7 @@
 
 	fmt.Fprintf(cli.out, "Containers: %d\n", remoteInfo.GetInt("Containers"))
 	fmt.Fprintf(cli.out, "Images: %d\n", remoteInfo.GetInt("Images"))
-	fmt.Fprintf(cli.out, "Driver: %s\n", remoteInfo.Get("Driver"))
+	fmt.Fprintf(cli.out, "Storage Driver: %s\n", remoteInfo.Get("Driver"))
 	var driverStatus [][2]string
 	if err := remoteInfo.GetJson("DriverStatus", &driverStatus); err != nil {
 		return err
@@ -440,14 +441,15 @@
 	for _, pair := range driverStatus {
 		fmt.Fprintf(cli.out, " %s: %s\n", pair[0], pair[1])
 	}
+	fmt.Fprintf(cli.out, "Execution Driver: %s\n", remoteInfo.Get("ExecutionDriver"))
+	fmt.Fprintf(cli.out, "Kernel Version: %s\n", remoteInfo.Get("KernelVersion"))
+
 	if remoteInfo.GetBool("Debug") || os.Getenv("DEBUG") != "" {
 		fmt.Fprintf(cli.out, "Debug mode (server): %v\n", remoteInfo.GetBool("Debug"))
 		fmt.Fprintf(cli.out, "Debug mode (client): %v\n", os.Getenv("DEBUG") != "")
 		fmt.Fprintf(cli.out, "Fds: %d\n", remoteInfo.GetInt("NFd"))
 		fmt.Fprintf(cli.out, "Goroutines: %d\n", remoteInfo.GetInt("NGoroutines"))
-		fmt.Fprintf(cli.out, "Execution Driver: %s\n", remoteInfo.Get("ExecutionDriver"))
 		fmt.Fprintf(cli.out, "EventsListeners: %d\n", remoteInfo.GetInt("NEventsListener"))
-		fmt.Fprintf(cli.out, "Kernel Version: %s\n", remoteInfo.Get("KernelVersion"))
 
 		if initSha1 := remoteInfo.Get("InitSha1"); initSha1 != "" {
 			fmt.Fprintf(cli.out, "Init SHA1: %s\n", initSha1)
@@ -533,13 +535,23 @@
 
 func (cli *DockerCli) forwardAllSignals(cid string) chan os.Signal {
 	sigc := make(chan os.Signal, 1)
-	utils.CatchAll(sigc)
+	signal.CatchAll(sigc)
 	go func() {
 		for s := range sigc {
 			if s == syscall.SIGCHLD {
 				continue
 			}
-			if _, _, err := readBody(cli.call("POST", fmt.Sprintf("/containers/%s/kill?signal=%d", cid, s), nil, false)); err != nil {
+			var sig string
+			for sigStr, sigN := range signal.SignalMap {
+				if sigN == s {
+					sig = sigStr
+					break
+				}
+			}
+			if sig == "" {
+				utils.Errorf("Unsupported signal: %d. Discarding.", s)
+			}
+			if _, _, err := readBody(cli.call("POST", fmt.Sprintf("/containers/%s/kill?signal=%s", cid, sig), nil, false)); err != nil {
 				utils.Debugf("Error sending signal: %s", err)
 			}
 		}
@@ -581,7 +593,7 @@
 
 		if !container.Config.Tty {
 			sigc := cli.forwardAllSignals(cmd.Arg(0))
-			defer utils.StopCatch(sigc)
+			defer signal.StopCatch(sigc)
 		}
 
 		var in io.ReadCloser
@@ -1614,7 +1626,7 @@
 
 	if *proxy && !container.Config.Tty {
 		sigc := cli.forwardAllSignals(cmd.Arg(0))
-		defer utils.StopCatch(sigc)
+		defer signal.StopCatch(sigc)
 	}
 
 	if err := cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), container.Config.Tty, in, cli.out, cli.err, nil); err != nil {
@@ -1753,7 +1765,21 @@
 		if containerIDFile, err = os.Create(hostConfig.ContainerIDFile); err != nil {
 			return fmt.Errorf("Failed to create the container ID file: %s", err)
 		}
-		defer containerIDFile.Close()
+		defer func() {
+			containerIDFile.Close()
+			var (
+				cidFileInfo os.FileInfo
+				err         error
+			)
+			if cidFileInfo, err = os.Stat(hostConfig.ContainerIDFile); err != nil {
+				return
+			}
+			if cidFileInfo.Size() == 0 {
+				if err := os.Remove(hostConfig.ContainerIDFile); err != nil {
+					fmt.Printf("failed to remove CID file '%s': %s \n", hostConfig.ContainerIDFile, err)
+				}
+			}
+		}()
 	}
 
 	containerValues := url.Values{}
@@ -1818,7 +1844,7 @@
 
 	if sigProxy {
 		sigc := cli.forwardAllSignals(runResult.Get("Id"))
-		defer utils.StopCatch(sigc)
+		defer signal.StopCatch(sigc)
 	}
 
 	var (
@@ -2239,7 +2265,12 @@
 					if setRawTerminal && cli.isTerminal {
 						term.RestoreTerminal(cli.terminalFd, oldState)
 					}
-					in.Close()
+					// For some reason this Close call blocks on darwin..
+					// As the client exists right after, simply discard the close
+					// until we find a better solution.
+					if goruntime.GOOS != "darwin" {
+						in.Close()
+					}
 				}
 			}()
 
@@ -2320,7 +2351,7 @@
 	cli.resizeTty(id)
 
 	sigchan := make(chan os.Signal, 1)
-	signal.Notify(sigchan, syscall.SIGWINCH)
+	gosignal.Notify(sigchan, syscall.SIGWINCH)
 	go func() {
 		for _ = range sigchan {
 			cli.resizeTty(id)
diff --git a/api/server.go b/api/server.go
index 6fafe60..771f3c6 100644
--- a/api/server.go
+++ b/api/server.go
@@ -26,7 +26,6 @@
 	"strconv"
 	"strings"
 	"syscall"
-	"time"
 )
 
 var (
@@ -883,7 +882,7 @@
 
 	var copyData engine.Env
 
-	if contentType := r.Header.Get("Content-Type"); contentType == "application/json" {
+	if contentType := r.Header.Get("Content-Type"); MatchesContentType(contentType, "application/json") {
 		if err := copyData.Decode(r.Body); err != nil {
 			return err
 		}
@@ -1130,7 +1129,7 @@
 
 // ListenAndServe sets up the required http.Server and gets it listening for
 // each addr passed in and does protocol specific checking.
-func ListenAndServe(proto, addr string, eng *engine.Engine, logging, enableCors bool, dockerVersion string, socketGroup string) error {
+func ListenAndServe(proto, addr string, eng *engine.Engine, logging, enableCors bool, dockerVersion, socketGroup string) error {
 	r, err := createRouter(eng, logging, enableCors, dockerVersion)
 
 	if err != nil {
@@ -1147,7 +1146,7 @@
 		}
 	}
 
-	l, err := listenbuffer.NewListenBuffer(proto, addr, activationLock, 15*time.Minute)
+	l, err := listenbuffer.NewListenBuffer(proto, addr, activationLock)
 	if err != nil {
 		return err
 	}
diff --git a/container.go b/container.go
index 50332f2..42b905a 100644
--- a/container.go
+++ b/container.go
@@ -363,14 +363,18 @@
 		driverConfig []string
 	)
 
+	en = &execdriver.Network{
+		Mtu:       c.runtime.config.Mtu,
+		Interface: nil,
+	}
+
 	if !c.Config.NetworkDisabled {
 		network := c.NetworkSettings
-		en = &execdriver.Network{
+		en.Interface = &execdriver.NetworkInterface{
 			Gateway:     network.Gateway,
 			Bridge:      network.Bridge,
 			IPAddress:   network.IPAddress,
 			IPPrefixLen: network.IPPrefixLen,
-			Mtu:         c.runtime.config.Mtu,
 		}
 	}
 
@@ -784,7 +788,7 @@
 		utils.Errorf("Error running container: %s", err)
 	}
 
-	if container.runtime.srv.IsRunning() {
+	if container.runtime != nil && container.runtime.srv != nil && container.runtime.srv.IsRunning() {
 		container.State.SetStopped(exitCode)
 
 		// FIXME: there is a race condition here which causes this to fail during the unit tests.
diff --git a/contrib/init/sysvinit-debian/docker b/contrib/init/sysvinit-debian/docker
index 510683a..67f0d28 100755
--- a/contrib/init/sysvinit-debian/docker
+++ b/contrib/init/sysvinit-debian/docker
@@ -21,6 +21,7 @@
 # modify these in /etc/default/$BASE (/etc/default/docker)
 DOCKER=/usr/bin/$BASE
 DOCKER_PIDFILE=/var/run/$BASE.pid
+DOCKER_LOGFILE=/var/log/$BASE.log
 DOCKER_OPTS=
 DOCKER_DESC="Docker"
 
@@ -50,23 +51,37 @@
 	fi
 }
 
+cgroupfs_mount() {
+	# see also https://github.com/tianon/cgroupfs-mount/blob/master/cgroupfs-mount
+	if grep -v '^#' /etc/fstab | grep -q cgroup \
+		|| [ ! -e /proc/cgroups ] \
+		|| [ ! -d /sys/fs/cgroup ]; then
+		return
+	fi
+	if ! mountpoint -q /sys/fs/cgroup; then
+		mount -t tmpfs -o uid=0,gid=0,mode=0755 cgroup /sys/fs/cgroup
+	fi
+	(
+		cd /sys/fs/cgroup
+		for sys in $(awk '!/^#/ { if ($4 == 1) print $1 }' /proc/cgroups); do
+			mkdir -p $sys
+			if ! mountpoint -q $sys; then
+				if ! mount -n -t cgroup -o $sys cgroup $sys; then
+					rmdir $sys || true
+				fi
+			fi
+		done
+	)
+}
+
 case "$1" in
 	start)
 		fail_unless_root
 
-		if ! grep -q cgroup /proc/mounts; then
-			# rough approximation of cgroupfs-mount
-			mount -t tmpfs -o uid=0,gid=0,mode=0755 cgroup /sys/fs/cgroup
-			for sys in $(cut -d'	' -f1 /proc/cgroups); do
-				mkdir -p /sys/fs/cgroup/$sys
-				if ! mount -n -t cgroup -o $sys cgroup /sys/fs/cgroup/$sys 2>/dev/null; then
-					rmdir /sys/fs/cgroup/$sys 2>/dev/null || true
-				fi
-			done
-		fi
+		cgroupfs_mount
 
-		touch /var/log/docker.log
-		chgrp docker /var/log/docker.log
+		touch "$DOCKER_LOGFILE"
+		chgrp docker "$DOCKER_LOGFILE"
 
 		log_begin_msg "Starting $DOCKER_DESC: $BASE"
 		start-stop-daemon --start --background \
@@ -76,7 +91,7 @@
 			-- \
 				-d -p "$DOCKER_PIDFILE" \
 				$DOCKER_OPTS \
-					> /var/log/docker.log 2>&1
+					>> "$DOCKER_LOGFILE" 2>&1
 		log_end_msg $?
 		;;
 
diff --git a/contrib/init/upstart/docker.conf b/contrib/init/upstart/docker.conf
index e2cc453..047f21c 100644
--- a/contrib/init/upstart/docker.conf
+++ b/contrib/init/upstart/docker.conf
@@ -5,6 +5,29 @@
 
 respawn
 
+pre-start script
+	# see also https://github.com/tianon/cgroupfs-mount/blob/master/cgroupfs-mount
+	if grep -v '^#' /etc/fstab | grep -q cgroup \
+		|| [ ! -e /proc/cgroups ] \
+		|| [ ! -d /sys/fs/cgroup ]; then
+		exit 0
+	fi
+	if ! mountpoint -q /sys/fs/cgroup; then
+		mount -t tmpfs -o uid=0,gid=0,mode=0755 cgroup /sys/fs/cgroup
+	fi
+	(
+		cd /sys/fs/cgroup
+		for sys in $(awk '!/^#/ { if ($4 == 1) print $1 }' /proc/cgroups); do
+			mkdir -p $sys
+			if ! mountpoint -q $sys; then
+				if ! mount -n -t cgroup -o $sys cgroup $sys; then
+					rmdir $sys || true
+				fi
+			fi
+		done
+	)
+end script
+
 script
 	# modify these in /etc/default/$UPSTART_JOB (/etc/default/docker)
 	DOCKER=/usr/bin/$UPSTART_JOB
@@ -12,15 +35,5 @@
 	if [ -f /etc/default/$UPSTART_JOB ]; then
 		. /etc/default/$UPSTART_JOB
 	fi
-	if ! grep -q cgroup /proc/mounts; then
-		# rough approximation of cgroupfs-mount
-		mount -t tmpfs -o uid=0,gid=0,mode=0755 cgroup /sys/fs/cgroup
-		for sys in $(cut -d'	' -f1 /proc/cgroups); do
-			mkdir -p /sys/fs/cgroup/$sys
-			if ! mount -n -t cgroup -o $sys cgroup /sys/fs/cgroup/$sys 2>/dev/null; then
-				rmdir /sys/fs/cgroup/$sys 2>/dev/null || true
-			fi
-		done
-	fi
 	"$DOCKER" -d $DOCKER_OPTS
 end script
diff --git a/docs/sources/articles/security.rst b/docs/sources/articles/security.rst
index 3dc5780..e738e9a 100644
--- a/docs/sources/articles/security.rst
+++ b/docs/sources/articles/security.rst
@@ -7,7 +7,7 @@
 Docker Security
 ===============
 
-  *Adapted from* `Containers & Docker: How Secure are They? <blogsecurity>`_
+  *Adapted from* `Containers & Docker: How Secure are They? <blogsecurity_>`_
 
 There are three major areas to consider when reviewing Docker security:
 
@@ -261,7 +261,7 @@
 
 For more context and especially for comparisons with VMs and other
 container systems, please also see the `original blog post
-<blogsecurity>`_.
+<blogsecurity_>`_.
 
 .. _blogsecurity: http://blog.docker.io/2013/08/containers-docker-how-secure-are-they/
 
diff --git a/docs/sources/reference/commandline/cli.rst b/docs/sources/reference/commandline/cli.rst
index 2e49cd5..9e99671 100644
--- a/docs/sources/reference/commandline/cli.rst
+++ b/docs/sources/reference/commandline/cli.rst
@@ -88,7 +88,7 @@
       -v, --version=false: Print version information and quit
       --mtu=0: Set the containers network MTU; if no value is provided: default to the default route MTU or 1500 if no default route is available
 
-The Docker daemon is the persistent process that manages containers.  Docker uses the same binary for both the 
+The Docker daemon is the persistent process that manages containers.  Docker uses the same binary for both the
 daemon and client.  To run the daemon you provide the ``-d`` flag.
 
 To force Docker to use devicemapper as the storage driver, use ``docker -d -s devicemapper``.
@@ -100,10 +100,10 @@
 To use lxc as the execution driver, use ``docker -d -e lxc``.
 
 The docker client will also honor the ``DOCKER_HOST`` environment variable to set
-the ``-H`` flag for the client.  
+the ``-H`` flag for the client.
 
 ::
- 
+
         docker -H tcp://0.0.0.0:4243 ps
         # or
         export DOCKER_HOST="tcp://0.0.0.0:4243"
@@ -141,7 +141,7 @@
 
 You can detach from the container again (and leave it running) with
 ``CTRL-c`` (for a quiet exit) or ``CTRL-\`` to get a stacktrace of
-the Docker client when it quits.  When you detach from the container's 
+the Docker client when it quits.  When you detach from the container's
 process the exit code will be returned to the client.
 
 To stop a container, use ``docker stop``.
@@ -303,7 +303,7 @@
 
       -m, --message="": Commit message
       -a, --author="": Author (eg. "John Hannibal Smith <hannibal@a-team.com>"
-      --run="": Configuration to be applied when the image is launched with `docker run`.
+      --run="": Configuration changes to be applied when the image is launched with `docker run`.
                (ex: -run='{"Cmd": ["cat", "/world"], "PortSpecs": ["22"]}')
 
 .. _cli_commit_examples:
@@ -315,14 +315,14 @@
 
 	$ sudo docker ps
 	ID                  IMAGE               COMMAND             CREATED             STATUS              PORTS
-	c3f279d17e0a        ubuntu:12.04        /bin/bash           7 days ago          Up 25 hours                             
-	197387f1b436        ubuntu:12.04        /bin/bash           7 days ago          Up 25 hours                             
+	c3f279d17e0a        ubuntu:12.04        /bin/bash           7 days ago          Up 25 hours
+	197387f1b436        ubuntu:12.04        /bin/bash           7 days ago          Up 25 hours
 	$ docker commit c3f279d17e0a  SvenDowideit/testimage:version3
 	f5283438590d
 	$ docker images | head
 	REPOSITORY                        TAG                 ID                  CREATED             VIRTUAL SIZE
 	SvenDowideit/testimage            version3            f5283438590d        16 seconds ago      335.7 MB
-	
+
 Change the command that a container runs
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -344,11 +344,40 @@
         apt                     host.conf        lsb-base             rc2.d
         ...
 
+Merged configs example
+......................
+
+Say you have a Dockerfile like so:
+
+.. code-block:: bash
+
+        ENV MYVAR foobar
+        RUN apt-get install openssh
+        EXPOSE 22
+        CMD ["/usr/sbin/sshd -D"]
+        ...
+
+If you run that, make some changes, and then commit, Docker will merge the environment variable and exposed port configuration settings with any that you specify in the -run= option. This is a change from Docker 0.8.0 and prior where no attempt was made to preserve any existing configuration on commit.
+
+.. code-block:: bash
+
+        $ docker build -t me/foo .
+        $ docker run -t -i me/foo /bin/bash
+        foo-container$ [make changes in the container]
+        foo-container$ exit
+        $ docker commit -run='{"Cmd": ["ls"]}' [container-id] me/bar
+        ...
+
+The me/bar image will now have port 22 exposed, MYVAR env var set to 'foobar', and its default command will be ["ls"].
+
+Note that this is currently a shallow merge. So, for example, if you had specified a new port spec in the -run= config above, that would have clobbered the 'EXPOSE 22' setting from the parent container.
+
 Full -run example
 .................
 
 The ``--run`` JSON hash changes the ``Config`` section when running ``docker inspect CONTAINERID``
-or ``config`` when running ``docker inspect IMAGEID``.
+or ``config`` when running ``docker inspect IMAGEID``. Existing configuration key-values that are
+not overridden in the JSON hash will be merged in.
 
 (Multiline is okay within a single quote ``'``)
 
@@ -664,7 +693,7 @@
 
     Usage: docker import URL|- [REPOSITORY[:TAG]]
 
-    Create an empty filesystem image and import the contents of the tarball 
+    Create an empty filesystem image and import the contents of the tarball
     (.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz) into it, then optionally tag it.
 
 At this time, the URL must start with ``http`` and point to a single
@@ -942,7 +971,7 @@
 
     $ docker ps
     CONTAINER ID        IMAGE                        COMMAND                CREATED              STATUS              PORTS               NAMES
-    4c01db0b339c        ubuntu:12.04                 bash                   17 seconds ago       Up 16 seconds                           webapp              
+    4c01db0b339c        ubuntu:12.04                 bash                   17 seconds ago       Up 16 seconds                           webapp
     d7886598dbe2        crosbymichael/redis:latest   /redis-server --dir    33 minutes ago       Up 33 minutes       6379/tcp            redis,webapp/db
     fd2645e2e2b5        busybox:latest               top                    10 days ago          Ghost                                   insane_ptolemy
 
@@ -1047,7 +1076,7 @@
     Remove one or more images
 
       -f, --force=false: Force
-    
+
 Removing tagged images
 ~~~~~~~~~~~~~~~~~~~~~~
 
@@ -1126,8 +1155,8 @@
 The ``docker run`` command can be used in combination with ``docker commit`` to
 :ref:`change the command that a container runs <cli_commit_examples>`.
 
-See :ref:`port_redirection` for more detailed information about the ``--expose``, 
-``-p``, ``-P`` and ``--link`` parameters, and :ref:`working_with_links_names` for 
+See :ref:`port_redirection` for more detailed information about the ``--expose``,
+``-p``, ``-P`` and ``--link`` parameters, and :ref:`working_with_links_names` for
 specific examples using ``--link``.
 
 Known Issues (run -volumes-from)
@@ -1207,8 +1236,8 @@
 
    $ sudo docker run -t -i -v /var/run/docker.sock:/var/run/docker.sock -v ./static-docker:/usr/bin/docker busybox sh
 
-By bind-mounting the docker unix socket and statically linked docker binary 
-(such as that provided by https://get.docker.io), you give the container 
+By bind-mounting the docker unix socket and statically linked docker binary
+(such as that provided by https://get.docker.io), you give the container
 the full access to create and manipulate the host's docker daemon.
 
 .. code-block:: bash
diff --git a/execdriver/driver.go b/execdriver/driver.go
index ec8f48f..bb7aad2 100644
--- a/execdriver/driver.go
+++ b/execdriver/driver.go
@@ -84,11 +84,15 @@
 
 // Network settings of the container
 type Network struct {
+	Interface *NetworkInterface `json:"interface"` // if interface is nil then networking is disabled
+	Mtu       int               `json:"mtu"`
+}
+
+type NetworkInterface struct {
 	Gateway     string `json:"gateway"`
 	IPAddress   string `json:"ip"`
 	Bridge      string `json:"bridge"`
 	IPPrefixLen int    `json:"ip_prefix_len"`
-	Mtu         int    `json:"mtu"`
 }
 
 type Resources struct {
@@ -111,8 +115,8 @@
 	WorkingDir string     `json:"working_dir"`
 	ConfigPath string     `json:"config_path"` // this should be able to be removed when the lxc template is moved into the driver
 	Tty        bool       `json:"tty"`
-	Network    *Network   `json:"network"` // if network is nil then networking is disabled
-	Config     []string   `json:"config"`  //  generic values that specific drivers can consume
+	Network    *Network   `json:"network"`
+	Config     []string   `json:"config"` //  generic values that specific drivers can consume
 	Resources  *Resources `json:"resources"`
 
 	Terminal     Terminal `json:"-"`             // standard or tty terminal
diff --git a/execdriver/lxc/driver.go b/execdriver/lxc/driver.go
index 765a52e..f24b3b5 100644
--- a/execdriver/lxc/driver.go
+++ b/execdriver/lxc/driver.go
@@ -94,13 +94,15 @@
 		DriverName,
 	}
 
-	if c.Network != nil {
+	if c.Network.Interface != nil {
 		params = append(params,
-			"-g", c.Network.Gateway,
-			"-i", fmt.Sprintf("%s/%d", c.Network.IPAddress, c.Network.IPPrefixLen),
-			"-mtu", strconv.Itoa(c.Network.Mtu),
+			"-g", c.Network.Interface.Gateway,
+			"-i", fmt.Sprintf("%s/%d", c.Network.Interface.IPAddress, c.Network.Interface.IPPrefixLen),
 		)
 	}
+	params = append(params,
+		"-mtu", strconv.Itoa(c.Network.Mtu),
+	)
 
 	if c.User != "" {
 		params = append(params, "-u", c.User)
@@ -168,6 +170,9 @@
 	// Poll lxc for RUNNING status
 	pid, err := d.waitForStart(c, waitLock)
 	if err != nil {
+		if c.Process != nil {
+			c.Process.Kill()
+		}
 		return -1, err
 	}
 	c.ContainerPid = pid
diff --git a/execdriver/lxc/info.go b/execdriver/lxc/info.go
index 3b2ea0d..27b4c58 100644
--- a/execdriver/lxc/info.go
+++ b/execdriver/lxc/info.go
@@ -36,7 +36,7 @@
 		if len(parts) < 2 {
 			continue
 		}
-		switch strings.TrimSpace(parts[0]) {
+		switch strings.ToLower(strings.TrimSpace(parts[0])) {
 		case "state":
 			info.Running = strings.TrimSpace(parts[1]) == "RUNNING"
 		case "pid":
diff --git a/execdriver/lxc/lxc_template.go b/execdriver/lxc/lxc_template.go
index 1181396..03d01e8 100644
--- a/execdriver/lxc/lxc_template.go
+++ b/execdriver/lxc/lxc_template.go
@@ -7,17 +7,17 @@
 )
 
 const LxcTemplate = `
-{{if .Network}}
+{{if .Network.Interface}}
 # network configuration
 lxc.network.type = veth
-lxc.network.link = {{.Network.Bridge}}
+lxc.network.link = {{.Network.Interface.Bridge}}
 lxc.network.name = eth0
-lxc.network.mtu = {{.Network.Mtu}}
 {{else}}
 # network is disabled (-n=false)
 lxc.network.type = empty
 lxc.network.flags = up
 {{end}}
+lxc.network.mtu = {{.Network.Mtu}}
 
 # root filesystem
 {{$ROOTFS := .Rootfs}}
diff --git a/execdriver/lxc/lxc_template_unit_test.go b/execdriver/lxc/lxc_template_unit_test.go
index 99d6e63..6fea86d 100644
--- a/execdriver/lxc/lxc_template_unit_test.go
+++ b/execdriver/lxc/lxc_template_unit_test.go
@@ -43,6 +43,10 @@
 			Memory:    int64(mem),
 			CpuShares: int64(cpu),
 		},
+		Network: &execdriver.Network{
+			Mtu:       1500,
+			Interface: nil,
+		},
 	}
 	p, err := driver.generateLXCConfig(command)
 	if err != nil {
@@ -75,6 +79,10 @@
 			"lxc.utsname = docker",
 			"lxc.cgroup.cpuset.cpus = 0,1",
 		},
+		Network: &execdriver.Network{
+			Mtu:       1500,
+			Interface: nil,
+		},
 	}
 
 	p, err := driver.generateLXCConfig(command)
diff --git a/execdriver/native/default_template.go b/execdriver/native/default_template.go
index 6e7d597..62d8040 100644
--- a/execdriver/native/default_template.go
+++ b/execdriver/native/default_template.go
@@ -19,19 +19,30 @@
 	container.WorkingDir = c.WorkingDir
 	container.Env = c.Env
 
-	if c.Network != nil {
-		container.Networks = []*libcontainer.Network{
-			{
-				Mtu:     c.Network.Mtu,
-				Address: fmt.Sprintf("%s/%d", c.Network.IPAddress, c.Network.IPPrefixLen),
-				Gateway: c.Network.Gateway,
-				Type:    "veth",
-				Context: libcontainer.Context{
-					"prefix": "veth",
-					"bridge": c.Network.Bridge,
-				},
+	loopbackNetwork := libcontainer.Network{
+		Mtu:     c.Network.Mtu,
+		Address: fmt.Sprintf("%s/%d", "127.0.0.1", 0),
+		Gateway: "localhost",
+		Type:    "loopback",
+		Context: libcontainer.Context{},
+	}
+
+	container.Networks = []*libcontainer.Network{
+		&loopbackNetwork,
+	}
+
+	if c.Network.Interface != nil {
+		vethNetwork := libcontainer.Network{
+			Mtu:     c.Network.Mtu,
+			Address: fmt.Sprintf("%s/%d", c.Network.Interface.IPAddress, c.Network.Interface.IPPrefixLen),
+			Gateway: c.Network.Interface.Gateway,
+			Type:    "veth",
+			Context: libcontainer.Context{
+				"prefix": "veth",
+				"bridge": c.Network.Interface.Bridge,
 			},
 		}
+		container.Networks = append(container.Networks, &vethNetwork)
 	}
 
 	container.Cgroups.Name = c.ID
diff --git a/graphdriver/devmapper/deviceset.go b/graphdriver/devmapper/deviceset.go
index 303e363..4d33e24 100644
--- a/graphdriver/devmapper/deviceset.go
+++ b/graphdriver/devmapper/deviceset.go
@@ -39,6 +39,13 @@
 	// first get (since we need to mount to set up the device
 	// a bit first).
 	floating bool `json:"-"`
+
+	// The global DeviceSet lock guarantees that we serialize all
+	// the calls to libdevmapper (which is not threadsafe), but we
+	// sometimes release that lock while sleeping. In that case
+	// this per-device lock is still held, protecting against
+	// other accesses to the device that we're doing the wait on.
+	lock sync.Mutex `json:"-"`
 }
 
 type MetaData struct {
@@ -47,7 +54,7 @@
 
 type DeviceSet struct {
 	MetaData
-	sync.Mutex
+	sync.Mutex       // Protects Devices map and serializes calls into libdevmapper
 	root             string
 	devicePrefix     string
 	TransactionId    uint64
@@ -569,6 +576,9 @@
 		return fmt.Errorf("Error adding device for '%s': can't find device for parent '%s'", hash, baseHash)
 	}
 
+	baseInfo.lock.Lock()
+	defer baseInfo.lock.Unlock()
+
 	deviceId := devices.allocateDeviceId()
 
 	if err := devices.createSnapDevice(devices.getPoolDevName(), deviceId, baseInfo.Name(), baseInfo.DeviceId); err != nil {
@@ -636,6 +646,14 @@
 	devices.Lock()
 	defer devices.Unlock()
 
+	info := devices.Devices[hash]
+	if info == nil {
+		return fmt.Errorf("Unknown device %s", hash)
+	}
+
+	info.lock.Lock()
+	defer info.lock.Unlock()
+
 	return devices.deleteDevice(hash)
 }
 
@@ -683,7 +701,7 @@
 func (devices *DeviceSet) removeDeviceAndWait(devname string) error {
 	var err error
 
-	for i := 0; i < 10; i++ {
+	for i := 0; i < 1000; i++ {
 		devices.sawBusy = false
 		err = removeDevice(devname)
 		if err == nil {
@@ -695,7 +713,9 @@
 
 		// If we see EBUSY it may be a transient error,
 		// sleep a bit a retry a few times.
-		time.Sleep(5 * time.Millisecond)
+		devices.Unlock()
+		time.Sleep(10 * time.Millisecond)
+		devices.Lock()
 	}
 	if err != nil {
 		return err
@@ -709,7 +729,7 @@
 
 // waitRemove blocks until either:
 // a) the device registered at <device_set_prefix>-<hash> is removed,
-// or b) the 1 second timeout expires.
+// or b) the 10 second timeout expires.
 func (devices *DeviceSet) waitRemove(devname string) error {
 	utils.Debugf("[deviceset %s] waitRemove(%s)", devices.devicePrefix, devname)
 	defer utils.Debugf("[deviceset %s] waitRemove(%s) END", devices.devicePrefix, devname)
@@ -728,7 +748,9 @@
 			break
 		}
 
-		time.Sleep(1 * time.Millisecond)
+		devices.Unlock()
+		time.Sleep(10 * time.Millisecond)
+		devices.Lock()
 	}
 	if i == 1000 {
 		return fmt.Errorf("Timeout while waiting for device %s to be removed", devname)
@@ -738,7 +760,7 @@
 
 // waitClose blocks until either:
 // a) the device registered at <device_set_prefix>-<hash> is closed,
-// or b) the 1 second timeout expires.
+// or b) the 10 second timeout expires.
 func (devices *DeviceSet) waitClose(hash string) error {
 	info := devices.Devices[hash]
 	if info == nil {
@@ -756,7 +778,9 @@
 		if devinfo.OpenCount == 0 {
 			break
 		}
-		time.Sleep(1 * time.Millisecond)
+		devices.Unlock()
+		time.Sleep(10 * time.Millisecond)
+		devices.Lock()
 	}
 	if i == 1000 {
 		return fmt.Errorf("Timeout while waiting for device %s to close", hash)
@@ -773,20 +797,26 @@
 	defer utils.Debugf("[deviceset %s] shutdown END", devices.devicePrefix)
 
 	for _, info := range devices.Devices {
+		info.lock.Lock()
 		if info.mountCount > 0 {
 			if err := sysUnmount(info.mountPath, 0); err != nil {
 				utils.Debugf("Shutdown unmounting %s, error: %s\n", info.mountPath, err)
 			}
 		}
+		info.lock.Unlock()
 	}
 
 	for _, d := range devices.Devices {
+		d.lock.Lock()
+
 		if err := devices.waitClose(d.Hash); err != nil {
 			utils.Errorf("Warning: error waiting for device %s to unmount: %s\n", d.Hash, err)
 		}
 		if err := devices.deactivateDevice(d.Hash); err != nil {
 			utils.Debugf("Shutdown deactivate %s , error: %s\n", d.Hash, err)
 		}
+
+		d.lock.Unlock()
 	}
 
 	if err := devices.deactivatePool(); err != nil {
@@ -805,6 +835,9 @@
 		return fmt.Errorf("Unknown device %s", hash)
 	}
 
+	info.lock.Lock()
+	defer info.lock.Unlock()
+
 	if info.mountCount > 0 {
 		if path != info.mountPath {
 			return fmt.Errorf("Trying to mount devmapper device in multple places (%s, %s)", info.mountPath, path)
@@ -851,6 +884,9 @@
 		return fmt.Errorf("UnmountDevice: no such device %s\n", hash)
 	}
 
+	info.lock.Lock()
+	defer info.lock.Unlock()
+
 	if mode == UnmountFloat {
 		if info.floating {
 			return fmt.Errorf("UnmountDevice: can't float floating reference %s\n", hash)
@@ -920,6 +956,10 @@
 	if info == nil {
 		return false
 	}
+
+	info.lock.Lock()
+	defer info.lock.Unlock()
+
 	devinfo, _ := getInfo(info.Name())
 	return devinfo != nil && devinfo.Exists != 0
 }
@@ -974,6 +1014,9 @@
 		return nil, fmt.Errorf("No device %s", hash)
 	}
 
+	info.lock.Lock()
+	defer info.lock.Unlock()
+
 	status := &DevStatus{
 		DeviceId:      info.DeviceId,
 		Size:          info.Size,
diff --git a/graphdriver/devmapper/driver.go b/graphdriver/devmapper/driver.go
index 4d414f9..8c5a19e 100644
--- a/graphdriver/devmapper/driver.go
+++ b/graphdriver/devmapper/driver.go
@@ -90,6 +90,13 @@
 }
 
 func (d *Driver) Remove(id string) error {
+	if !d.DeviceSet.HasDevice(id) {
+		// Consider removing a non-existing device a no-op
+		// This is useful to be able to progress on container removal
+		// if the underlying device has gone away due to earlier errors
+		return nil
+	}
+
 	// Sink the float from create in case no Get() call was made
 	if err := d.DeviceSet.UnmountDevice(id, UnmountSink); err != nil {
 		return err
diff --git a/hack/make.sh b/hack/make.sh
index 63edca4..50886eb 100755
--- a/hack/make.sh
+++ b/hack/make.sh
@@ -141,6 +141,27 @@
 	\) -name "$1" -print0 | xargs -0n1 dirname | sort -u
 }
 
+hash_files() {
+	while [ $# -gt 0 ]; do
+		f="$1"
+		shift
+		dir="$(dirname "$f")"
+		base="$(basename "$f")"
+		for hashAlgo in md5 sha256; do
+			if command -v "${hashAlgo}sum" &> /dev/null; then
+				(
+					# subshell and cd so that we get output files like:
+					#   $HASH docker-$VERSION
+					# instead of:
+					#   $HASH /go/src/github.com/.../$VERSION/binary/docker-$VERSION
+					cd "$dir"
+					"${hashAlgo}sum" "$base" > "$base.$hashAlgo"
+				)
+			fi
+		done
+	done
+}
+
 bundle() {
 	bundlescript=$1
 	bundle=$(basename $bundlescript)
diff --git a/hack/make/binary b/hack/make/binary
old mode 100644
new mode 100755
index 7272b1e..7b4d7b5
--- a/hack/make/binary
+++ b/hack/make/binary
@@ -3,7 +3,7 @@
 DEST=$1
 
 go build \
-	-o $DEST/docker-$VERSION \
+	-o "$DEST/docker-$VERSION" \
 	"${BUILDFLAGS[@]}" \
 	-ldflags "
 		$LDFLAGS
@@ -11,3 +11,5 @@
 	" \
 	./docker
 echo "Created binary: $DEST/docker-$VERSION"
+
+hash_files "$DEST/docker-$VERSION"
diff --git a/hack/make/dynbinary b/hack/make/dynbinary
index d4f583f..75cffe3 100644
--- a/hack/make/dynbinary
+++ b/hack/make/dynbinary
@@ -5,7 +5,7 @@
 if [ -z "$DOCKER_CLIENTONLY" ]; then
 	# dockerinit still needs to be a static binary, even if docker is dynamic
 	go build \
-		-o $DEST/dockerinit-$VERSION \
+		-o "$DEST/dockerinit-$VERSION" \
 		"${BUILDFLAGS[@]}" \
 		-ldflags "
 			$LDFLAGS
@@ -14,7 +14,9 @@
 		" \
 		./dockerinit
 	echo "Created binary: $DEST/dockerinit-$VERSION"
-	ln -sf dockerinit-$VERSION $DEST/dockerinit
+	ln -sf "dockerinit-$VERSION" "$DEST/dockerinit"
+	
+	hash_files "$DEST/dockerinit-$VERSION"
 	
 	sha1sum=
 	if command -v sha1sum &> /dev/null; then
diff --git a/hack/make/tgz b/hack/make/tgz
index 5d03306..1203399 100644
--- a/hack/make/tgz
+++ b/hack/make/tgz
@@ -23,6 +23,8 @@
 	
 	tar --numeric-owner --owner 0 -C "$DEST/build" -czf "$TGZ" usr
 	
+	hash_files "$TGZ"
+	
 	rm -rf "$DEST/build"
 	
 	echo "Created tgz: $TGZ"
diff --git a/hack/release.sh b/hack/release.sh
index 50913dd..c771fb7 100755
--- a/hack/release.sh
+++ b/hack/release.sh
@@ -55,33 +55,16 @@
 if [ "$1" != '--release-regardless-of-test-failure' ]; then
 	RELEASE_BUNDLES=( test "${RELEASE_BUNDLES[@]}" )
 fi
-
-if ! ./hack/make.sh "${RELEASE_BUNDLES[@]}"; then
-	echo >&2
-	echo >&2 'The build or tests appear to have failed.'
-	echo >&2
-	echo >&2 'You, as the release  maintainer, now have a couple options:'
-	echo >&2 '- delay release and fix issues'
-	echo >&2 '- delay release and fix issues'
-	echo >&2 '- did we mention how important this is?  issues need fixing :)'
-	echo >&2
-	echo >&2 'As a final LAST RESORT, you (because only you, the release maintainer,'
-	echo >&2 ' really knows all the hairy problems at hand with the current release'
-	echo >&2 ' issues) may bypass this checking by running this script again with the'
-	echo >&2 ' single argument of "--release-regardless-of-test-failure", which will skip'
-	echo >&2 ' running the test suite, and will only build the binaries and packages.  Please'
-	echo >&2 ' avoid using this if at all possible.'
-	echo >&2
-	echo >&2 'Regardless, we cannot stress enough the scarcity with which this bypass'
-	echo >&2 ' should be used.  If there are release issues, we should always err on the'
-	echo >&2 ' side of caution.'
-	echo >&2
-	exit 1
-fi
-
+	
 VERSION=$(cat VERSION)
 BUCKET=$AWS_S3_BUCKET
 
+# These are the 2 keys we've used to sign the deb's
+#   release (get.docker.io)
+#	GPG_KEY="36A1D7869245C8950F966E92D8576A8BA88D21E9"
+#   test    (test.docker.io)
+#	GPG_KEY="740B314AE3941731B942C66ADF4FD13717AAD7D6"
+
 setup_s3() {
 	# Try creating the bucket. Ignore errors (it might already exist).
 	s3cmd mb s3://$BUCKET 2>/dev/null || true
@@ -114,76 +97,138 @@
 	esac
 }
 
+build_all() {
+	if ! ./hack/make.sh "${RELEASE_BUNDLES[@]}"; then
+		echo >&2
+		echo >&2 'The build or tests appear to have failed.'
+		echo >&2
+		echo >&2 'You, as the release  maintainer, now have a couple options:'
+		echo >&2 '- delay release and fix issues'
+		echo >&2 '- delay release and fix issues'
+		echo >&2 '- did we mention how important this is?  issues need fixing :)'
+		echo >&2
+		echo >&2 'As a final LAST RESORT, you (because only you, the release maintainer,'
+		echo >&2 ' really knows all the hairy problems at hand with the current release'
+		echo >&2 ' issues) may bypass this checking by running this script again with the'
+		echo >&2 ' single argument of "--release-regardless-of-test-failure", which will skip'
+		echo >&2 ' running the test suite, and will only build the binaries and packages.  Please'
+		echo >&2 ' avoid using this if at all possible.'
+		echo >&2
+		echo >&2 'Regardless, we cannot stress enough the scarcity with which this bypass'
+		echo >&2 ' should be used.  If there are release issues, we should always err on the'
+		echo >&2 ' side of caution.'
+		echo >&2
+		exit 1
+	fi
+}
+
+upload_release_build() {
+	src="$1"
+	dst="$2"
+	latest="$3"
+
+	echo
+	echo "Uploading $src"
+	echo "  to $dst"
+	echo
+	s3cmd --follow-symlinks --preserve --acl-public put "$src" "$dst"
+	if [ "$latest" ]; then
+		echo
+		echo "Copying to $latest"
+		echo
+		s3cmd --acl-public cp "$dst" "$latest"
+	fi
+
+	# get hash files too (see hash_files() in hack/make.sh)
+	for hashAlgo in md5 sha256; do
+		if [ -e "$src.$hashAlgo" ]; then
+			echo
+			echo "Uploading $src.$hashAlgo"
+			echo "  to $dst.$hashAlgo"
+			echo
+			s3cmd --follow-symlinks --preserve --acl-public --mime-type='text/plain' put "$src.$hashAlgo" "$dst.$hashAlgo"
+			if [ "$latest" ]; then
+				echo
+				echo "Copying to $latest.$hashAlgo"
+				echo
+				s3cmd --acl-public cp "$dst.$hashAlgo" "$latest.$hashAlgo"
+			fi
+		fi
+	done
+}
+
 release_build() {
 	GOOS=$1
 	GOARCH=$2
 
-	BINARY=bundles/$VERSION/cross/$GOOS/$GOARCH/docker-$VERSION
-	TGZ=bundles/$VERSION/tgz/$GOOS/$GOARCH/docker-$VERSION.tgz
+	binDir=bundles/$VERSION/cross/$GOOS/$GOARCH
+	tgzDir=bundles/$VERSION/tgz/$GOOS/$GOARCH
+	binary=docker-$VERSION
+	tgz=docker-$VERSION.tgz
+
+	latestBase=
+	if [ -z "$NOLATEST" ]; then
+		latestBase=docker-latest
+	fi
 
 	# we need to map our GOOS and GOARCH to uname values
 	# see https://en.wikipedia.org/wiki/Uname
 	# ie, GOOS=linux -> "uname -s"=Linux
 
-	S3OS=$GOOS
-	case "$S3OS" in
+	s3Os=$GOOS
+	case "$s3Os" in
 		darwin)
-			S3OS=Darwin
+			s3Os=Darwin
 			;;
 		freebsd)
-			S3OS=FreeBSD
+			s3Os=FreeBSD
 			;;
 		linux)
-			S3OS=Linux
+			s3Os=Linux
 			;;
 		*)
-			echo >&2 "error: can't convert $S3OS to an appropriate value for 'uname -s'"
+			echo >&2 "error: can't convert $s3Os to an appropriate value for 'uname -s'"
 			exit 1
 			;;
 	esac
 
-	S3ARCH=$GOARCH
-	case "$S3ARCH" in
+	s3Arch=$GOARCH
+	case "$s3Arch" in
 		amd64)
-			S3ARCH=x86_64
+			s3Arch=x86_64
 			;;
 		386)
-			S3ARCH=i386
+			s3Arch=i386
 			;;
 		arm)
-			S3ARCH=armel
+			s3Arch=armel
 			# someday, we might potentially support mutliple GOARM values, in which case we might get armhf here too
 			;;
 		*)
-			echo >&2 "error: can't convert $S3ARCH to an appropriate value for 'uname -m'"
+			echo >&2 "error: can't convert $s3Arch to an appropriate value for 'uname -m'"
 			exit 1
 			;;
 	esac
 
-	S3DIR=s3://$BUCKET/builds/$S3OS/$S3ARCH
+	s3Dir=s3://$BUCKET/builds/$s3Os/$s3Arch
+	latest=
+	latestTgz=
+	if [ "$latestBase" ]; then
+		latest="$s3Dir/$latestBase"
+		latestTgz="$s3Dir/$latestBase.tgz"
+	fi
 
-	if [ ! -x "$BINARY" ]; then
-		echo >&2 "error: can't find $BINARY - was it compiled properly?"
+	if [ ! -x "$binDir/$binary" ]; then
+		echo >&2 "error: can't find $binDir/$binary - was it compiled properly?"
 		exit 1
 	fi
-	if [ ! -f "$TGZ" ]; then
-		echo >&2 "error: can't find $TGZ - was it packaged properly?"
+	if [ ! -f "$tgzDir/$tgz" ]; then
+		echo >&2 "error: can't find $tgzDir/$tgz - was it packaged properly?"
 		exit 1
 	fi
 
-	echo "Uploading $BINARY to $S3OS/$S3ARCH/docker-$VERSION"
-	s3cmd --follow-symlinks --preserve --acl-public put $BINARY $S3DIR/docker-$VERSION
-
-	echo "Uploading $TGZ to $S3OS/$S3ARCH/docker-$VERSION.tgz"
-	s3cmd --follow-symlinks --preserve --acl-public put $TGZ $S3DIR/docker-$VERSION.tgz
-
-	if [ -z "$NOLATEST" ]; then
-		echo "Copying $S3OS/$S3ARCH/docker-$VERSION to $S3OS/$S3ARCH/docker-latest"
-		s3cmd --acl-public cp $S3DIR/docker-$VERSION $S3DIR/docker-latest
-
-		echo "Copying $S3OS/$S3ARCH/docker-$VERSION.tgz to $S3OS/$S3ARCH/docker-latest.tgz"
-		s3cmd --acl-public cp $S3DIR/docker-$VERSION.tgz $S3DIR/docker-latest.tgz
-	fi
+	upload_release_build "$binDir/$binary" "$s3Dir/$binary" "$latest"
+	upload_release_build "$tgzDir/$tgz" "$s3Dir/$tgz" "$latestTgz"
 }
 
 # Upload the 'ubuntu' bundle to S3:
@@ -194,21 +239,6 @@
 		echo >&2 './hack/make.sh must be run before release_ubuntu'
 		exit 1
 	}
-	# Make sure that we have our keys
-	mkdir -p /.gnupg/
-	s3cmd sync s3://$BUCKET/ubuntu/.gnupg/ /.gnupg/ || true
-	gpg --list-keys releasedocker >/dev/null || {
-		gpg --gen-key --batch <<EOF
-Key-Type: RSA
-Key-Length: 2048
-Passphrase: $GPG_PASSPHRASE
-Name-Real: Docker Release Tool
-Name-Email: docker@dotcloud.com
-Name-Comment: releasedocker
-Expire-Date: 0
-%commit
-EOF
-	}
 
 	# Sign our packages
 	dpkg-sig -g "--passphrase $GPG_PASSPHRASE" -k releasedocker \
@@ -305,8 +335,28 @@
 	fi
 }
 
+setup_gpg() {
+	# Make sure that we have our keys
+	mkdir -p /.gnupg/
+	s3cmd sync s3://$BUCKET/ubuntu/.gnupg/ /.gnupg/ || true
+	gpg --list-keys releasedocker >/dev/null || {
+		gpg --gen-key --batch <<EOF
+Key-Type: RSA
+Key-Length: 4096
+Passphrase: $GPG_PASSPHRASE
+Name-Real: Docker Release Tool
+Name-Email: docker@dotcloud.com
+Name-Comment: releasedocker
+Expire-Date: 0
+%commit
+EOF
+	}
+}
+
 main() {
+	build_all
 	setup_s3
+	setup_gpg
 	release_binaries
 	release_ubuntu
 	release_index
diff --git a/integration/commands_test.go b/integration/commands_test.go
index 9f7a413..f254973 100644
--- a/integration/commands_test.go
+++ b/integration/commands_test.go
@@ -930,7 +930,7 @@
 // #2098 - Docker cidFiles only contain short version of the containerId
 //sudo docker run --cidfile /tmp/docker_test.cid ubuntu echo "test"
 // TestRunCidFile tests that run --cidfile returns the longid
-func TestRunCidFile(t *testing.T) {
+func TestRunCidFileCheckIDLength(t *testing.T) {
 	stdout, stdoutPipe := io.Pipe()
 
 	tmpDir, err := ioutil.TempDir("", "TestRunCidFile")
@@ -979,6 +979,35 @@
 
 }
 
+// Ensure that CIDFile gets deleted if it's empty
+// Perform this test by making `docker run` fail
+func TestRunCidFileCleanupIfEmpty(t *testing.T) {
+	tmpDir, err := ioutil.TempDir("", "TestRunCidFile")
+	if err != nil {
+		t.Fatal(err)
+	}
+	tmpCidFile := path.Join(tmpDir, "cid")
+
+	cli := api.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto, testDaemonAddr)
+	defer cleanup(globalEngine, t)
+
+	c := make(chan struct{})
+	go func() {
+		defer close(c)
+		if err := cli.CmdRun("--cidfile", tmpCidFile, unitTestImageID); err == nil {
+			t.Fatal("running without a command should haveve failed")
+		}
+		if _, err := os.Stat(tmpCidFile); err == nil {
+			t.Fatalf("empty CIDFile '%s' should've been deleted", tmpCidFile)
+		}
+	}()
+	defer os.RemoveAll(tmpDir)
+
+	setTimeout(t, "CmdRun timed out", 5*time.Second, func() {
+		<-c
+	})
+}
+
 func TestContainerOrphaning(t *testing.T) {
 
 	// setup a temporary directory
diff --git a/integration/container_test.go b/integration/container_test.go
index 4efb95a..980fb44 100644
--- a/integration/container_test.go
+++ b/integration/container_test.go
@@ -434,28 +434,6 @@
 	}
 }
 
-func TestContainerNetwork(t *testing.T) {
-	runtime := mkRuntime(t)
-	defer nuke(runtime)
-	container, _, err := runtime.Create(
-		&runconfig.Config{
-			Image: GetTestImage(runtime).ID,
-			Cmd:   []string{"ping", "-c", "1", "127.0.0.1"},
-		},
-		"",
-	)
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer runtime.Destroy(container)
-	if err := container.Run(); err != nil {
-		t.Fatal(err)
-	}
-	if code := container.State.GetExitCode(); code != 0 {
-		t.Fatalf("Unexpected ping 127.0.0.1 exit code %d (expected 0)", code)
-	}
-}
-
 func TestKillDifferentUser(t *testing.T) {
 	runtime := mkRuntime(t)
 	defer nuke(runtime)
@@ -1523,6 +1501,53 @@
 	}
 }
 
+func TestContainerNetwork(t *testing.T) {
+	runtime := mkRuntime(t)
+	defer nuke(runtime)
+	container, _, err := runtime.Create(
+		&runconfig.Config{
+			Image: GetTestImage(runtime).ID,
+			// If I change this to ping 8.8.8.8 it fails.  Any idea why? - timthelion
+			Cmd: []string{"ping", "-c", "1", "127.0.0.1"},
+		},
+		"",
+	)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer runtime.Destroy(container)
+	if err := container.Run(); err != nil {
+		t.Fatal(err)
+	}
+	if code := container.State.GetExitCode(); code != 0 {
+		t.Fatalf("Unexpected ping 127.0.0.1 exit code %d (expected 0)", code)
+	}
+}
+
+// Issue #4681
+func TestLoopbackFunctionsWhenNetworkingIsDissabled(t *testing.T) {
+	runtime := mkRuntime(t)
+	defer nuke(runtime)
+	container, _, err := runtime.Create(
+		&runconfig.Config{
+			Image:           GetTestImage(runtime).ID,
+			Cmd:             []string{"ping", "-c", "1", "127.0.0.1"},
+			NetworkDisabled: true,
+		},
+		"",
+	)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer runtime.Destroy(container)
+	if err := container.Run(); err != nil {
+		t.Fatal(err)
+	}
+	if code := container.State.GetExitCode(); code != 0 {
+		t.Fatalf("Unexpected ping 127.0.0.1 exit code %d (expected 0)", code)
+	}
+}
+
 func TestOnlyLoopbackExistsWhenUsingDisableNetworkOption(t *testing.T) {
 	eng := NewTestEngine(t)
 	runtime := mkRuntimeFromEngine(eng, t)
diff --git a/integration/server_test.go b/integration/server_test.go
index 69a9052..e978177 100644
--- a/integration/server_test.go
+++ b/integration/server_test.go
@@ -281,6 +281,63 @@
 	}
 }
 
+func TestMergeConfigOnCommit(t *testing.T) {
+	eng := NewTestEngine(t)
+	runtime := mkRuntimeFromEngine(eng, t)
+	defer runtime.Nuke()
+
+	container1, _, _ := mkContainer(runtime, []string{"-e", "FOO=bar", unitTestImageID, "echo test > /tmp/foo"}, t)
+	defer runtime.Destroy(container1)
+
+	config, _, _, err := runconfig.Parse([]string{container1.ID, "cat /tmp/foo"}, nil)
+	if err != nil {
+		t.Error(err)
+	}
+
+	job := eng.Job("commit", container1.ID)
+	job.Setenv("repo", "testrepo")
+	job.Setenv("tag", "testtag")
+	job.SetenvJson("config", config)
+	var newId string
+	job.Stdout.AddString(&newId)
+	if err := job.Run(); err != nil {
+		t.Error(err)
+	}
+
+	container2, _, _ := mkContainer(runtime, []string{newId}, t)
+	defer runtime.Destroy(container2)
+
+	job = eng.Job("inspect", container1.Name, "container")
+	baseContainer, _ := job.Stdout.AddEnv()
+	if err := job.Run(); err != nil {
+		t.Error(err)
+	}
+
+	job = eng.Job("inspect", container2.Name, "container")
+	commitContainer, _ := job.Stdout.AddEnv()
+	if err := job.Run(); err != nil {
+		t.Error(err)
+	}
+
+	baseConfig := baseContainer.GetSubEnv("Config")
+	commitConfig := commitContainer.GetSubEnv("Config")
+
+	if commitConfig.Get("Env") != baseConfig.Get("Env") {
+		t.Fatalf("Env config in committed container should be %v, was %v",
+			baseConfig.Get("Env"), commitConfig.Get("Env"))
+	}
+
+	if baseConfig.Get("Cmd") != "[\"echo test \\u003e /tmp/foo\"]" {
+		t.Fatalf("Cmd in base container should be [\"echo test \\u003e /tmp/foo\"], was %s",
+			baseConfig.Get("Cmd"))
+	}
+
+	if commitConfig.Get("Cmd") != "[\"cat /tmp/foo\"]" {
+		t.Fatalf("Cmd in committed container should be [\"cat /tmp/foo\"], was %s",
+			commitConfig.Get("Cmd"))
+	}
+}
+
 func TestRestartKillWait(t *testing.T) {
 	eng := NewTestEngine(t)
 	srv := mkServerFromEngine(eng, t)
diff --git a/pkg/libcontainer/apparmor/setup.go b/pkg/libcontainer/apparmor/setup.go
index e07759c..4e1c951 100644
--- a/pkg/libcontainer/apparmor/setup.go
+++ b/pkg/libcontainer/apparmor/setup.go
@@ -5,6 +5,7 @@
 	"io/ioutil"
 	"os"
 	"os/exec"
+	"path"
 )
 
 const DefaultProfilePath = "/etc/apparmor.d/docker"
@@ -85,6 +86,11 @@
 		return nil
 	}
 
+	// Make sure /etc/apparmor.d exists
+	if err := os.MkdirAll(path.Dir(DefaultProfilePath), 0755); err != nil {
+		return err
+	}
+
 	if err := ioutil.WriteFile(DefaultProfilePath, []byte(DefaultProfile), 0644); err != nil {
 		return err
 	}
diff --git a/pkg/libcontainer/network/loopback.go b/pkg/libcontainer/network/loopback.go
new file mode 100644
index 0000000..6215061
--- /dev/null
+++ b/pkg/libcontainer/network/loopback.go
@@ -0,0 +1,24 @@
+package network
+
+import (
+	"fmt"
+	"github.com/dotcloud/docker/pkg/libcontainer"
+)
+
+// Loopback is a network strategy that provides a basic loopback device
+type Loopback struct {
+}
+
+func (l *Loopback) Create(n *libcontainer.Network, nspid int, context libcontainer.Context) error {
+	return nil
+}
+
+func (l *Loopback) Initialize(config *libcontainer.Network, context libcontainer.Context) error {
+	if err := SetMtu("lo", config.Mtu); err != nil {
+		return fmt.Errorf("set lo mtu to %d %s", config.Mtu, err)
+	}
+	if err := InterfaceUp("lo"); err != nil {
+		return fmt.Errorf("lo up %s", err)
+	}
+	return nil
+}
diff --git a/pkg/libcontainer/network/strategy.go b/pkg/libcontainer/network/strategy.go
index 234fcc0..693790d 100644
--- a/pkg/libcontainer/network/strategy.go
+++ b/pkg/libcontainer/network/strategy.go
@@ -10,7 +10,8 @@
 )
 
 var strategies = map[string]NetworkStrategy{
-	"veth": &Veth{},
+	"veth":     &Veth{},
+	"loopback": &Loopback{},
 }
 
 // NetworkStrategy represents a specific network configuration for
diff --git a/pkg/libcontainer/network/veth.go b/pkg/libcontainer/network/veth.go
index 3ab1b23..3df0cd6 100644
--- a/pkg/libcontainer/network/veth.go
+++ b/pkg/libcontainer/network/veth.go
@@ -68,12 +68,6 @@
 	if err := InterfaceUp("eth0"); err != nil {
 		return fmt.Errorf("eth0 up %s", err)
 	}
-	if err := SetMtu("lo", config.Mtu); err != nil {
-		return fmt.Errorf("set lo mtu to %d %s", config.Mtu, err)
-	}
-	if err := InterfaceUp("lo"); err != nil {
-		return fmt.Errorf("lo up %s", err)
-	}
 	if config.Gateway != "" {
 		if err := SetDefaultGateway(config.Gateway); err != nil {
 			return fmt.Errorf("set gateway to %s %s", config.Gateway, err)
diff --git a/pkg/libcontainer/nsinit/execin.go b/pkg/libcontainer/nsinit/execin.go
index 488fe0e..628854f 100644
--- a/pkg/libcontainer/nsinit/execin.go
+++ b/pkg/libcontainer/nsinit/execin.go
@@ -14,9 +14,12 @@
 
 // ExecIn uses an existing pid and joins the pid's namespaces with the new command.
 func (ns *linuxNs) ExecIn(container *libcontainer.Container, nspid int, args []string) (int, error) {
-	for _, ns := range container.Namespaces {
-		if err := system.Unshare(ns.Value); err != nil {
-			return -1, err
+	for _, nsv := range container.Namespaces {
+		// skip the PID namespace on unshare because it it not supported
+		if nsv.Key != "NEWPID" {
+			if err := system.Unshare(nsv.Value); err != nil {
+				return -1, err
+			}
 		}
 	}
 	fds, err := ns.getNsFds(nspid, container)
diff --git a/pkg/libcontainer/nsinit/init.go b/pkg/libcontainer/nsinit/init.go
index 336fc1e..09f85e2 100644
--- a/pkg/libcontainer/nsinit/init.go
+++ b/pkg/libcontainer/nsinit/init.go
@@ -48,7 +48,9 @@
 			return fmt.Errorf("setctty %s", err)
 		}
 	}
-	if err := system.ParentDeathSignal(); err != nil {
+	// this is our best effort to let the process know that the parent has died and that it
+	// should it should act on it how it sees fit
+	if err := system.ParentDeathSignal(uintptr(syscall.SIGTERM)); err != nil {
 		return fmt.Errorf("parent death signal %s", err)
 	}
 	if err := setupNewMountNamespace(rootfs, console, container.ReadonlyFs, container.NoPivotRoot); err != nil {
@@ -124,7 +126,11 @@
 		if err != nil {
 			return err
 		}
-		return strategy.Initialize(config, context)
+
+		err1 := strategy.Initialize(config, context)
+		if err1 != nil {
+			return err1
+		}
 	}
 	return nil
 }
diff --git a/pkg/libcontainer/nsinit/mount.go b/pkg/libcontainer/nsinit/mount.go
index 83577cf..072188e 100644
--- a/pkg/libcontainer/nsinit/mount.go
+++ b/pkg/libcontainer/nsinit/mount.go
@@ -46,10 +46,8 @@
 	if err := setupDev(rootfs); err != nil {
 		return err
 	}
-	if console != "" {
-		if err := setupPtmx(rootfs, console); err != nil {
-			return err
-		}
+	if err := setupPtmx(rootfs, console); err != nil {
+		return err
 	}
 	if err := system.Chdir(rootfs); err != nil {
 		return fmt.Errorf("chdir into %s %s", rootfs, err)
@@ -245,8 +243,10 @@
 	if err := os.Symlink("pts/ptmx", ptmx); err != nil {
 		return fmt.Errorf("symlink dev ptmx %s", err)
 	}
-	if err := setupConsole(rootfs, console); err != nil {
-		return err
+	if console != "" {
+		if err := setupConsole(rootfs, console); err != nil {
+			return err
+		}
 	}
 	return nil
 }
diff --git a/pkg/listenbuffer/buffer.go b/pkg/listenbuffer/buffer.go
index c350805..17572c8 100644
--- a/pkg/listenbuffer/buffer.go
+++ b/pkg/listenbuffer/buffer.go
@@ -5,15 +5,10 @@
 */
 package listenbuffer
 
-import (
-	"fmt"
-	"net"
-	"time"
-)
+import "net"
 
-// NewListenBuffer returns a listener listening on addr with the protocol.  It sets the
-// timeout to wait on first connection before an error is returned
-func NewListenBuffer(proto, addr string, activate chan struct{}, timeout time.Duration) (net.Listener, error) {
+// NewListenBuffer returns a listener listening on addr with the protocol.
+func NewListenBuffer(proto, addr string, activate chan struct{}) (net.Listener, error) {
 	wrapped, err := net.Listen(proto, addr)
 	if err != nil {
 		return nil, err
@@ -22,7 +17,6 @@
 	return &defaultListener{
 		wrapped:  wrapped,
 		activate: activate,
-		timeout:  timeout,
 	}, nil
 }
 
@@ -30,7 +24,6 @@
 	wrapped  net.Listener // the real listener to wrap
 	ready    bool         // is the listner ready to start accpeting connections
 	activate chan struct{}
-	timeout  time.Duration // how long to wait before we consider this an error
 }
 
 func (l *defaultListener) Close() error {
@@ -47,15 +40,7 @@
 	if l.ready {
 		return l.wrapped.Accept()
 	}
-
-	select {
-	case <-time.After(l.timeout):
-		// close the connection so any clients are disconnected
-		l.Close()
-		return nil, fmt.Errorf("timeout (%s) reached waiting for listener to become ready", l.timeout.String())
-	case <-l.activate:
-		l.ready = true
-		return l.Accept()
-	}
-	panic("unreachable")
+	<-l.activate
+	l.ready = true
+	return l.Accept()
 }
diff --git a/pkg/mflag/example/example.go b/pkg/mflag/example/example.go
index ed940e8..ce9dd30 100644
--- a/pkg/mflag/example/example.go
+++ b/pkg/mflag/example/example.go
@@ -13,7 +13,8 @@
 
 func init() {
 	flag.Bool([]string{"#hp", "#-halp"}, false, "display the halp")
-	flag.BoolVar(&b, []string{"b"}, false, "a simple bool")
+	flag.BoolVar(&b, []string{"b", "#bal", "#bol", "-bal"}, false, "a simple bool")
+	flag.BoolVar(&b, []string{"g", "#gil"}, false, "a simple bool")
 	flag.BoolVar(&b2, []string{"#-bool"}, false, "a simple bool")
 	flag.IntVar(&i, []string{"-integer", "-number"}, -1, "a simple integer")
 	flag.StringVar(&str, []string{"s", "#hidden", "-string"}, "", "a simple string") //-s -hidden and --string will work, but -hidden won't be in the usage
diff --git a/pkg/mflag/flag.go b/pkg/mflag/flag.go
index 7125c03..5810410 100644
--- a/pkg/mflag/flag.go
+++ b/pkg/mflag/flag.go
@@ -805,9 +805,20 @@
 		f.actual = make(map[string]*Flag)
 	}
 	f.actual[name] = flag
-	for _, n := range flag.Names {
+	for i, n := range flag.Names {
 		if n == fmt.Sprintf("#%s", name) {
-			fmt.Fprintf(f.out(), "Warning: '-%s' is deprecated, it will be removed soon. See usage.\n", name)
+			replacement := ""
+			for j := i; j < len(flag.Names); j++ {
+				if flag.Names[j][0] != '#' {
+					replacement = flag.Names[j]
+					break
+				}
+			}
+			if replacement != "" {
+				fmt.Fprintf(f.out(), "Warning: '-%s' is deprecated, it will be replaced by '-%s' soon. See usage.\n", name, replacement)
+			} else {
+				fmt.Fprintf(f.out(), "Warning: '-%s' is deprecated, it will be removed soon. See usage.\n", name)
+			}
 		}
 	}
 	return true, "", nil
diff --git a/pkg/signal/signal.go b/pkg/signal/signal.go
new file mode 100644
index 0000000..6333754
--- /dev/null
+++ b/pkg/signal/signal.go
@@ -0,0 +1,19 @@
+package signal
+
+import (
+	"os"
+	"os/signal"
+)
+
+func CatchAll(sigc chan os.Signal) {
+	handledSigs := []os.Signal{}
+	for _, s := range SignalMap {
+		handledSigs = append(handledSigs, s)
+	}
+	signal.Notify(sigc, handledSigs...)
+}
+
+func StopCatch(sigc chan os.Signal) {
+	signal.Stop(sigc)
+	close(sigc)
+}
diff --git a/pkg/signal/signal_darwin.go b/pkg/signal/signal_darwin.go
new file mode 100644
index 0000000..fcd3a8f
--- /dev/null
+++ b/pkg/signal/signal_darwin.go
@@ -0,0 +1,40 @@
+package signal
+
+import (
+	"syscall"
+)
+
+var SignalMap = map[string]syscall.Signal{
+	"ABRT":   syscall.SIGABRT,
+	"ALRM":   syscall.SIGALRM,
+	"BUG":    syscall.SIGBUS,
+	"CHLD":   syscall.SIGCHLD,
+	"CONT":   syscall.SIGCONT,
+	"EMT":    syscall.SIGEMT,
+	"FPE":    syscall.SIGFPE,
+	"HUP":    syscall.SIGHUP,
+	"ILL":    syscall.SIGILL,
+	"INFO":   syscall.SIGINFO,
+	"INT":    syscall.SIGINT,
+	"IO":     syscall.SIGIO,
+	"IOT":    syscall.SIGIOT,
+	"KILL":   syscall.SIGKILL,
+	"PIPE":   syscall.SIGPIPE,
+	"PROF":   syscall.SIGPROF,
+	"QUIT":   syscall.SIGQUIT,
+	"SEGV":   syscall.SIGSEGV,
+	"STOP":   syscall.SIGSTOP,
+	"SYS":    syscall.SIGSYS,
+	"TERM":   syscall.SIGTERM,
+	"TRAP":   syscall.SIGTRAP,
+	"TSTP":   syscall.SIGTSTP,
+	"TTIN":   syscall.SIGTTIN,
+	"TTOU":   syscall.SIGTTOU,
+	"URG":    syscall.SIGURG,
+	"USR1":   syscall.SIGUSR1,
+	"USR2":   syscall.SIGUSR2,
+	"VTALRM": syscall.SIGVTALRM,
+	"WINCH":  syscall.SIGWINCH,
+	"XCPU":   syscall.SIGXCPU,
+	"XFSZ":   syscall.SIGXFSZ,
+}
diff --git a/pkg/signal/signal_freebsd.go b/pkg/signal/signal_freebsd.go
new file mode 100644
index 0000000..da042d7
--- /dev/null
+++ b/pkg/signal/signal_freebsd.go
@@ -0,0 +1,44 @@
+package signal
+
+import (
+	"os"
+	"os/signal"
+	"syscall"
+)
+
+var SignalMap = map[string]syscall.Signal{
+	"ABRT":   syscall.SIGABRT,
+	"ALRM":   syscall.SIGALRM,
+	"BUF":    syscall.SIGBUS,
+	"CHLD":   syscall.SIGCHLD,
+	"CONT":   syscall.SIGCONT,
+	"EMT":    syscall.SIGEMT,
+	"FPE":    syscall.SIGFPE,
+	"HUP":    syscall.SIGHUP,
+	"ILL":    syscall.SIGILL,
+	"INFO":   syscall.SIGINFO,
+	"INT":    syscall.SIGINT,
+	"IO":     syscall.SIGIO,
+	"IOT":    syscall.SIGIOT,
+	"KILL":   syscall.SIGKILL,
+	"LWP":    syscall.SIGLWP,
+	"PIPE":   syscall.SIGPIPE,
+	"PROF":   syscall.SIGPROF,
+	"QUIT":   syscall.SIGQUIT,
+	"SEGV":   syscall.SIGSEGV,
+	"STOP":   syscall.SIGSTOP,
+	"SYS":    syscall.SIGSYS,
+	"TERM":   syscall.SIGTERM,
+	"THR":    syscall.SIGTHR,
+	"TRAP":   syscall.SIGTRAP,
+	"TSTP":   syscall.SIGTSTP,
+	"TTIN":   syscall.SIGTTIN,
+	"TTOU":   syscall.SIGTTOU,
+	"URG":    syscall.SIGURG,
+	"USR1":   syscall.SIGUSR1,
+	"USR2":   syscall.SIGUSR2,
+	"VTALRM": syscall.SIGVTALRM,
+	"WINCH":  syscall.SIGWINCH,
+	"XCPU":   syscall.SIGXCPU,
+	"XFSZ":   syscall.SIGXFSZ,
+}
diff --git a/pkg/signal/signal_linux.go b/pkg/signal/signal_linux.go
new file mode 100644
index 0000000..a62f79d
--- /dev/null
+++ b/pkg/signal/signal_linux.go
@@ -0,0 +1,43 @@
+package signal
+
+import (
+	"syscall"
+)
+
+var SignalMap = map[string]syscall.Signal{
+	"ABRT":   syscall.SIGABRT,
+	"ALRM":   syscall.SIGALRM,
+	"BUS":    syscall.SIGBUS,
+	"CHLD":   syscall.SIGCHLD,
+	"CLD":    syscall.SIGCLD,
+	"CONT":   syscall.SIGCONT,
+	"FPE":    syscall.SIGFPE,
+	"HUP":    syscall.SIGHUP,
+	"ILL":    syscall.SIGILL,
+	"INT":    syscall.SIGINT,
+	"IO":     syscall.SIGIO,
+	"IOT":    syscall.SIGIOT,
+	"KILL":   syscall.SIGKILL,
+	"PIPE":   syscall.SIGPIPE,
+	"POLL":   syscall.SIGPOLL,
+	"PROF":   syscall.SIGPROF,
+	"PWR":    syscall.SIGPWR,
+	"QUIT":   syscall.SIGQUIT,
+	"SEGV":   syscall.SIGSEGV,
+	"STKFLT": syscall.SIGSTKFLT,
+	"STOP":   syscall.SIGSTOP,
+	"SYS":    syscall.SIGSYS,
+	"TERM":   syscall.SIGTERM,
+	"TRAP":   syscall.SIGTRAP,
+	"TSTP":   syscall.SIGTSTP,
+	"TTIN":   syscall.SIGTTIN,
+	"TTOU":   syscall.SIGTTOU,
+	"UNUSED": syscall.SIGUNUSED,
+	"URG":    syscall.SIGURG,
+	"USR1":   syscall.SIGUSR1,
+	"USR2":   syscall.SIGUSR2,
+	"VTALRM": syscall.SIGVTALRM,
+	"WINCH":  syscall.SIGWINCH,
+	"XCPU":   syscall.SIGXCPU,
+	"XFSZ":   syscall.SIGXFSZ,
+}
diff --git a/pkg/signal/signal_unsupported.go b/pkg/signal/signal_unsupported.go
new file mode 100644
index 0000000..99f9465
--- /dev/null
+++ b/pkg/signal/signal_unsupported.go
@@ -0,0 +1,9 @@
+// +build !linux,!darwin,!freebsd
+
+package signal
+
+import (
+	"syscall"
+)
+
+var SignalMap = map[string]syscall.Signal{}
diff --git a/pkg/system/calls_linux.go b/pkg/system/calls_linux.go
index bf667c5..43c00ed 100644
--- a/pkg/system/calls_linux.go
+++ b/pkg/system/calls_linux.go
@@ -115,8 +115,8 @@
 	return syscall.Mknod(path, mode, dev)
 }
 
-func ParentDeathSignal() error {
-	if _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_SET_PDEATHSIG, uintptr(syscall.SIGKILL), 0); err != 0 {
+func ParentDeathSignal(sig uintptr) error {
+	if _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_SET_PDEATHSIG, sig, 0); err != 0 {
 		return err
 	}
 	return nil
diff --git a/pkg/term/termios_darwin.go b/pkg/term/termios_darwin.go
index 24e79de..11cd70d 100644
--- a/pkg/term/termios_darwin.go
+++ b/pkg/term/termios_darwin.go
@@ -9,16 +9,24 @@
 	getTermios = syscall.TIOCGETA
 	setTermios = syscall.TIOCSETA
 
-	ECHO   = 0x00000008
-	ONLCR  = 0x2
-	ISTRIP = 0x20
-	INLCR  = 0x40
-	ISIG   = 0x80
-	IGNCR  = 0x80
-	ICANON = 0x100
-	ICRNL  = 0x100
-	IXOFF  = 0x400
-	IXON   = 0x200
+	IGNBRK = syscall.IGNBRK
+	PARMRK = syscall.PARMRK
+	INLCR  = syscall.INLCR
+	IGNCR  = syscall.IGNCR
+	ECHONL = syscall.ECHONL
+	CSIZE  = syscall.CSIZE
+	ICRNL  = syscall.ICRNL
+	ISTRIP = syscall.ISTRIP
+	PARENB = syscall.PARENB
+	ECHO   = syscall.ECHO
+	ICANON = syscall.ICANON
+	ISIG   = syscall.ISIG
+	IXON   = syscall.IXON
+	BRKINT = syscall.BRKINT
+	INPCK  = syscall.INPCK
+	OPOST  = syscall.OPOST
+	CS8    = syscall.CS8
+	IEXTEN = syscall.IEXTEN
 )
 
 type Termios struct {
@@ -41,10 +49,13 @@
 	}
 
 	newState := oldState.termios
-	newState.Iflag &^= (ISTRIP | INLCR | IGNCR | IXON | IXOFF)
-	newState.Iflag |= ICRNL
-	newState.Oflag |= ONLCR
-	newState.Lflag &^= (ECHO | ICANON | ISIG)
+	newState.Iflag &^= (IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON)
+	newState.Oflag &^= OPOST
+	newState.Lflag &^= (ECHO | ECHONL | ICANON | ISIG | IEXTEN)
+	newState.Cflag &^= (CSIZE | PARENB)
+	newState.Cflag |= CS8
+	newState.Cc[syscall.VMIN] = 1
+	newState.Cc[syscall.VTIME] = 0
 
 	if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(setTermios), uintptr(unsafe.Pointer(&newState))); err != 0 {
 		return nil, err
diff --git a/server.go b/server.go
index 2c8a7ee..d6513d8 100644
--- a/server.go
+++ b/server.go
@@ -8,6 +8,7 @@
 	"github.com/dotcloud/docker/dockerversion"
 	"github.com/dotcloud/docker/engine"
 	"github.com/dotcloud/docker/pkg/graphdb"
+	"github.com/dotcloud/docker/pkg/signal"
 	"github.com/dotcloud/docker/registry"
 	"github.com/dotcloud/docker/runconfig"
 	"github.com/dotcloud/docker/utils"
@@ -18,7 +19,7 @@
 	"net/url"
 	"os"
 	"os/exec"
-	"os/signal"
+	gosignal "os/signal"
 	"path"
 	"path/filepath"
 	"runtime"
@@ -47,7 +48,7 @@
 	}
 	job.Logf("Setting up signal traps")
 	c := make(chan os.Signal, 1)
-	signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT)
+	gosignal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT)
 	go func() {
 		sig := <-c
 		log.Printf("Received signal '%v', exiting\n", sig)
@@ -122,56 +123,30 @@
 // for the container to exit.
 // If a signal is given, then just send it to the container and return.
 func (srv *Server) ContainerKill(job *engine.Job) engine.Status {
-	signalMap := map[string]syscall.Signal{
-		"HUP":  syscall.SIGHUP,
-		"INT":  syscall.SIGINT,
-		"QUIT": syscall.SIGQUIT,
-		"ILL":  syscall.SIGILL,
-		"TRAP": syscall.SIGTRAP,
-		"ABRT": syscall.SIGABRT,
-		"BUS":  syscall.SIGBUS,
-		"FPE":  syscall.SIGFPE,
-		"KILL": syscall.SIGKILL,
-		"USR1": syscall.SIGUSR1,
-		"SEGV": syscall.SIGSEGV,
-		"USR2": syscall.SIGUSR2,
-		"PIPE": syscall.SIGPIPE,
-		"ALRM": syscall.SIGALRM,
-		"TERM": syscall.SIGTERM,
-		//"STKFLT": syscall.SIGSTKFLT,
-		"CHLD":   syscall.SIGCHLD,
-		"CONT":   syscall.SIGCONT,
-		"STOP":   syscall.SIGSTOP,
-		"TSTP":   syscall.SIGTSTP,
-		"TTIN":   syscall.SIGTTIN,
-		"TTOU":   syscall.SIGTTOU,
-		"URG":    syscall.SIGURG,
-		"XCPU":   syscall.SIGXCPU,
-		"XFSZ":   syscall.SIGXFSZ,
-		"VTALRM": syscall.SIGVTALRM,
-		"PROF":   syscall.SIGPROF,
-		"WINCH":  syscall.SIGWINCH,
-		"IO":     syscall.SIGIO,
-		//"PWR":    syscall.SIGPWR,
-		"SYS": syscall.SIGSYS,
-	}
-
 	if n := len(job.Args); n < 1 || n > 2 {
 		return job.Errorf("Usage: %s CONTAINER [SIGNAL]", job.Name)
 	}
-	name := job.Args[0]
-	var sig uint64
+	var (
+		name = job.Args[0]
+		sig  uint64
+		err  error
+	)
+
+	// If we have a signal, look at it. Otherwise, do nothing
 	if len(job.Args) == 2 && job.Args[1] != "" {
-		sig = uint64(signalMap[job.Args[1]])
-		if sig == 0 {
-			var err error
-			// The largest legal signal is 31, so let's parse on 5 bits
-			sig, err = strconv.ParseUint(job.Args[1], 10, 5)
-			if err != nil {
+		// Check if we passed the singal as a number:
+		// The largest legal signal is 31, so let's parse on 5 bits
+		sig, err = strconv.ParseUint(job.Args[1], 10, 5)
+		if err != nil {
+			// The signal is not a number, treat it as a string
+			sig = uint64(signal.SignalMap[job.Args[1]])
+			if sig == 0 {
 				return job.Errorf("Invalid signal: %s", job.Args[1])
 			}
+
 		}
 	}
+
 	if container := srv.runtime.Get(name); container != nil {
 		// If no signal is passed, or SIGKILL, perform regular Kill (SIGKILL + wait())
 		if sig == 0 || syscall.Signal(sig) == syscall.SIGKILL {
@@ -1039,12 +1014,17 @@
 	if container == nil {
 		return job.Errorf("No such container: %s", name)
 	}
-	var config runconfig.Config
-	if err := job.GetenvJson("config", &config); err != nil {
+	var config = container.Config
+	var newConfig runconfig.Config
+	if err := job.GetenvJson("config", &newConfig); err != nil {
 		return job.Error(err)
 	}
 
-	img, err := srv.runtime.Commit(container, job.Getenv("repo"), job.Getenv("tag"), job.Getenv("comment"), job.Getenv("author"), &config)
+	if err := runconfig.Merge(&newConfig, config); err != nil {
+		return job.Error(err)
+	}
+
+	img, err := srv.runtime.Commit(container, job.Getenv("repo"), job.Getenv("tag"), job.Getenv("comment"), job.Getenv("author"), &newConfig)
 	if err != nil {
 		return job.Error(err)
 	}
@@ -1087,16 +1067,32 @@
 
 		if !srv.runtime.graph.Exists(id) {
 			out.Write(sf.FormatProgress(utils.TruncateID(id), "Pulling metadata", nil))
-			imgJSON, imgSize, err := r.GetRemoteImageJSON(id, endpoint, token)
-			if err != nil {
-				out.Write(sf.FormatProgress(utils.TruncateID(id), "Error pulling dependent layers", nil))
-				// FIXME: Keep going in case of error?
-				return err
-			}
-			img, err := NewImgJSON(imgJSON)
-			if err != nil {
-				out.Write(sf.FormatProgress(utils.TruncateID(id), "Error pulling dependent layers", nil))
-				return fmt.Errorf("Failed to parse json: %s", err)
+			var (
+				imgJSON []byte
+				imgSize int
+				err     error
+				img     *Image
+			)
+			retries := 5
+			for j := 1; j <= retries; j++ {
+				imgJSON, imgSize, err = r.GetRemoteImageJSON(id, endpoint, token)
+				if err != nil && j == retries {
+					out.Write(sf.FormatProgress(utils.TruncateID(id), "Error pulling dependent layers", nil))
+					return err
+				} else if err != nil {
+					time.Sleep(time.Duration(j) * 500 * time.Millisecond)
+					continue
+				}
+				img, err = NewImgJSON(imgJSON)
+				if err != nil && j == retries {
+					out.Write(sf.FormatProgress(utils.TruncateID(id), "Error pulling dependent layers", nil))
+					return fmt.Errorf("Failed to parse json: %s", err)
+				} else if err != nil {
+					time.Sleep(time.Duration(j) * 500 * time.Millisecond)
+					continue
+				} else {
+					break
+				}
 			}
 
 			// Get the layer
@@ -2390,7 +2386,13 @@
 }
 
 func (srv *Server) Close() error {
+	if srv == nil {
+		return nil
+	}
 	srv.SetRunning(false)
+	if srv.runtime == nil {
+		return nil
+	}
 	return srv.runtime.Close()
 }
 
diff --git a/utils/jsonmessage.go b/utils/jsonmessage.go
index 9050dda..f84cc42 100644
--- a/utils/jsonmessage.go
+++ b/utils/jsonmessage.go
@@ -85,7 +85,7 @@
 		return jm.Error
 	}
 	var endl string
-	if isTerminal {
+	if isTerminal && jm.Stream == "" {
 		// <ESC>[2K = erase entire current line
 		fmt.Fprintf(out, "%c[2K\r", 27)
 		endl = "\r"
diff --git a/utils/signal.go b/utils/signal.go
deleted file mode 100644
index 0cac7d1..0000000
--- a/utils/signal.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package utils
-
-import (
-	"os"
-	"os/signal"
-)
-
-func StopCatch(sigc chan os.Signal) {
-	signal.Stop(sigc)
-	close(sigc)
-}
diff --git a/utils/signal_darwin.go b/utils/signal_darwin.go
deleted file mode 100644
index 28730db..0000000
--- a/utils/signal_darwin.go
+++ /dev/null
@@ -1,44 +0,0 @@
-package utils
-
-import (
-	"os"
-	"os/signal"
-	"syscall"
-)
-
-func CatchAll(sigc chan os.Signal) {
-	signal.Notify(sigc,
-		syscall.SIGABRT,
-		syscall.SIGALRM,
-		syscall.SIGBUS,
-		syscall.SIGCHLD,
-		syscall.SIGCONT,
-		syscall.SIGEMT,
-		syscall.SIGFPE,
-		syscall.SIGHUP,
-		syscall.SIGILL,
-		syscall.SIGINFO,
-		syscall.SIGINT,
-		syscall.SIGIO,
-		syscall.SIGIOT,
-		syscall.SIGKILL,
-		syscall.SIGPIPE,
-		syscall.SIGPROF,
-		syscall.SIGQUIT,
-		syscall.SIGSEGV,
-		syscall.SIGSTOP,
-		syscall.SIGSYS,
-		syscall.SIGTERM,
-		syscall.SIGTRAP,
-		syscall.SIGTSTP,
-		syscall.SIGTTIN,
-		syscall.SIGTTOU,
-		syscall.SIGURG,
-		syscall.SIGUSR1,
-		syscall.SIGUSR2,
-		syscall.SIGVTALRM,
-		syscall.SIGWINCH,
-		syscall.SIGXCPU,
-		syscall.SIGXFSZ,
-	)
-}
diff --git a/utils/signal_linux.go b/utils/signal_linux.go
deleted file mode 100644
index 26cfd56..0000000
--- a/utils/signal_linux.go
+++ /dev/null
@@ -1,47 +0,0 @@
-package utils
-
-import (
-	"os"
-	"os/signal"
-	"syscall"
-)
-
-func CatchAll(sigc chan os.Signal) {
-	signal.Notify(sigc,
-		syscall.SIGABRT,
-		syscall.SIGALRM,
-		syscall.SIGBUS,
-		syscall.SIGCHLD,
-		syscall.SIGCLD,
-		syscall.SIGCONT,
-		syscall.SIGFPE,
-		syscall.SIGHUP,
-		syscall.SIGILL,
-		syscall.SIGINT,
-		syscall.SIGIO,
-		syscall.SIGIOT,
-		syscall.SIGKILL,
-		syscall.SIGPIPE,
-		syscall.SIGPOLL,
-		syscall.SIGPROF,
-		syscall.SIGPWR,
-		syscall.SIGQUIT,
-		syscall.SIGSEGV,
-		syscall.SIGSTKFLT,
-		syscall.SIGSTOP,
-		syscall.SIGSYS,
-		syscall.SIGTERM,
-		syscall.SIGTRAP,
-		syscall.SIGTSTP,
-		syscall.SIGTTIN,
-		syscall.SIGTTOU,
-		syscall.SIGUNUSED,
-		syscall.SIGURG,
-		syscall.SIGUSR1,
-		syscall.SIGUSR2,
-		syscall.SIGVTALRM,
-		syscall.SIGWINCH,
-		syscall.SIGXCPU,
-		syscall.SIGXFSZ,
-	)
-}