diff --git a/common/buf/multi_buffer.go b/common/buf/multi_buffer.go index dd8961501..95149b4a2 100644 --- a/common/buf/multi_buffer.go +++ b/common/buf/multi_buffer.go @@ -3,6 +3,7 @@ package buf import ( "io" "net" + "os" "v2ray.com/core/common" "v2ray.com/core/common/errors" @@ -22,7 +23,7 @@ func ReadAllToMultiBuffer(reader io.Reader) (MultiBuffer, error) { mb.Append(b) } if err != nil { - if errors.Cause(err) == io.EOF { + if errors.Cause(err) == io.EOF || errors.Cause(err) == os.ErrClosed { return mb, nil } mb.Release() diff --git a/common/errors/errors.go b/common/errors/errors.go index 3e5e09425..daac515d2 100644 --- a/common/errors/errors.go +++ b/common/errors/errors.go @@ -3,6 +3,7 @@ package errors // import "v2ray.com/core/common/errors" import ( "context" + "os" "strings" "v2ray.com/core/common/log" @@ -162,12 +163,27 @@ func Cause(err error) error { if err == nil { return nil } +L: for { - inner, ok := err.(hasInnerError) - if !ok || inner.Inner() == nil { - break + switch inner := err.(type) { + case hasInnerError: + if inner.Inner() == nil { + break L + } + err = inner.Inner() + case *os.PathError: + if inner.Err == nil { + break L + } + err = inner.Err + case *os.SyscallError: + if inner.Err == nil { + break L + } + err = inner.Err + default: + break L } - err = inner.Inner() } return err } diff --git a/common/platform/ctlcmd/ctlcmd.go b/common/platform/ctlcmd/ctlcmd.go index 28b5fd250..45611c1ca 100644 --- a/common/platform/ctlcmd/ctlcmd.go +++ b/common/platform/ctlcmd/ctlcmd.go @@ -16,7 +16,7 @@ import ( func Run(args []string, input io.Reader) (buf.MultiBuffer, error) { v2ctl := platform.GetToolLocation("v2ctl") if _, err := os.Stat(v2ctl); err != nil { - return nil, err + return nil, newError("v2ctl doesn't exist").Base(err) } errBuffer := &buf.MultiBuffer{} @@ -30,19 +30,19 @@ func Run(args []string, input io.Reader) (buf.MultiBuffer, error) { stdoutReader, err := cmd.StdoutPipe() if err != nil { - return nil, err + return nil, newError("failed to get stdout from v2ctl").Base(err) } defer stdoutReader.Close() if err := cmd.Start(); err != nil { - return nil, err + return nil, newError("failed to start v2ctl").Base(err) } var content buf.MultiBuffer loadTask := func() error { c, err := buf.ReadAllToMultiBuffer(stdoutReader) if err != nil { - return err + return newError("failed to read config").Base(err) } content = c return nil