Browse code

LCOW: Capture stderr on external process. Log actual error rather than throwaway

Signed-off-by: John Howard <jhoward@microsoft.com>

John Howard authored on 2018/08/15 07:07:46
Showing 2 changed files
... ...
@@ -5,6 +5,7 @@ import (
5 5
 	"fmt"
6 6
 	"io"
7 7
 	"os"
8
+	"runtime"
8 9
 	"strings"
9 10
 
10 11
 	"github.com/containerd/continuity/driver"
... ...
@@ -173,6 +174,9 @@ func StatAt(remote builder.Source, path string) (os.FileInfo, error) {
173 173
 func FullPath(remote builder.Source, path string) (string, error) {
174 174
 	fullPath, err := remote.Root().ResolveScopedPath(path, true)
175 175
 	if err != nil {
176
+		if runtime.GOOS == "windows" {
177
+			return "", fmt.Errorf("failed to resolve scoped path %s (%s): %s. Possible cause is a forbidden path outside the build context", path, fullPath, err)
178
+		}
176 179
 		return "", fmt.Errorf("Forbidden path outside the build context: %s (%s)", path, fullPath) // backwards compat with old error
177 180
 	}
178 181
 	return fullPath, nil
... ...
@@ -3,6 +3,7 @@
3 3
 package lcow // import "github.com/docker/docker/daemon/graphdriver/lcow"
4 4
 
5 5
 import (
6
+	"bytes"
6 7
 	"errors"
7 8
 	"fmt"
8 9
 	"io"
... ...
@@ -385,7 +386,15 @@ func (svm *serviceVM) deleteUnionMount(mountName string, disks ...hcsshim.Mapped
385 385
 }
386 386
 
387 387
 func (svm *serviceVM) runProcess(command string, stdin io.Reader, stdout io.Writer, stderr io.Writer) error {
388
-	process, err := svm.config.RunProcess(command, stdin, stdout, stderr)
388
+	var process hcsshim.Process
389
+	var err error
390
+	errOut := &bytes.Buffer{}
391
+
392
+	if stderr != nil {
393
+		process, err = svm.config.RunProcess(command, stdin, stdout, stderr)
394
+	} else {
395
+		process, err = svm.config.RunProcess(command, stdin, stdout, errOut)
396
+	}
389 397
 	if err != nil {
390 398
 		return err
391 399
 	}
... ...
@@ -398,7 +407,12 @@ func (svm *serviceVM) runProcess(command string, stdin io.Reader, stdout io.Writ
398 398
 	}
399 399
 
400 400
 	if exitCode != 0 {
401
-		return fmt.Errorf("svm.runProcess: command %s failed with exit code %d", command, exitCode)
401
+		// If the caller isn't explicitly capturing stderr output, then capture it here instead.
402
+		e := fmt.Sprintf("svm.runProcess: command %s failed with exit code %d", command, exitCode)
403
+		if stderr == nil {
404
+			e = fmt.Sprintf("%s. (%s)", e, errOut.String())
405
+		}
406
+		return fmt.Errorf(e)
402 407
 	}
403 408
 	return nil
404 409
 }