Skip to content

Commit

Permalink
Safe yet correct readpipe closer
Browse files Browse the repository at this point in the history
  • Loading branch information
ribasushi committed Mar 28, 2020
1 parent ccbd08b commit 7083445
Showing 1 changed file with 31 additions and 14 deletions.
45 changes: 31 additions & 14 deletions core/commands/dag/dag.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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() {
Expand All @@ -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 {
Expand Down

0 comments on commit 7083445

Please sign in to comment.