diff --git a/core/commands/dag/dag.go b/core/commands/dag/dag.go index 572a5230efa5..fa15b51990e9 100644 --- a/core/commands/dag/dag.go +++ b/core/commands/dag/dag.go @@ -275,17 +275,17 @@ The output of blocks happens in strict DAG-traversal, first-seen, order. }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { - c, err := cid.Decode(req.Arguments[0]) - if err != nil { + c, cidErr := cid.Decode(req.Arguments[0]) + if cidErr != nil { return fmt.Errorf( "unable to parse root specification (currently only bare CIDs are supported): %s", - err, + cidErr, ) } - node, err := cmdenv.GetNode(env) - if err != nil { - return err + node, nodeErr := cmdenv.GetNode(env) + if nodeErr != nil { + return nodeErr } // Code disabled until descent-issue in go-ipld-prime is fixed @@ -307,6 +307,24 @@ The output of blocks happens in strict DAG-traversal, first-seen, order. // if err := car.Write(pipeW); err != nil {} pipeR, pipeW := io.Pipe() + // this is so convoluted because we: + // - want to close the readpipe on error so that the goroutine dies + // - can not do so on success, because during a no-deamon process + // scenario the PostRun will not be able to grab the EOF from the + // now-closed pipe + // + // Skipping this check results in: + // + // cmd/ipfs/ipfs dag export QmdmQXB2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7RgQm >/dev/null + // 0s 0 B / ? [------------------------------------------------------------------------=]Error: io: read/write on closed pipe + // 1s 107.08 MiB / ? [-----------------------------------------=----------] 106.59 MiB/s + // + var emittingError error + defer func() { + if emittingError != nil { + pipeR.Close() + } + }() errCh := make(chan error, 2) // we only report the 1st error go func() { @@ -330,21 +348,20 @@ The output of blocks happens in strict DAG-traversal, first-seen, order. } }() - if err := res.Emit(pipeR); err != nil { - pipeR.Close() // ignore the error if any - return err + if emittingError = res.Emit(pipeR); emittingError != nil { + return emittingError } - err = <-errCh + emittingError = <-errCh // minimal user friendliness - if err != nil && + if emittingError != nil && !node.IsOnline && - err == ipld.ErrNotFound { - err = fmt.Errorf("%s (currently offline, perhaps retry after attaching to the network)", err) + emittingError == ipld.ErrNotFound { + emittingError = fmt.Errorf("%s (currently offline, perhaps retry after attaching to the network)", emittingError) } - return err + return emittingError }, PostRun: cmds.PostRunMap{ cmds.CLI: func(res cmds.Response, re cmds.ResponseEmitter) error {