Skip to content

Deadlock with connection.BlockFetch().Client.GetBlock #774

@igorcrevar

Description

@igorcrevar

If connection.BlockFetch().Client.GetBlock is executed on a closed connection, the next call will block indefinitely. I believe the issue is caused by a mutex that is not being unlocked. See the code below for reproduction:

func bugTest() error {
	connection, err := ouroboros.NewConnection(
		ouroboros.WithNetworkMagic(uint32(1)),
		ouroboros.WithNodeToNode(true),
	)
	if err != nil {
		return err
	}

	// dial some known node -> connect to node
	if err := connection.Dial("tcp", "preprod-node.play.dev.cardano.org:3001"); err != nil {
		return err
	}

	blockHash, err := hex.DecodeString("f7e99e7d597ef0b49ac4b442addb208b09ef928ee729487bc2d0a4e65dd11a66")
	if err != nil {
		return err
	}
        // some point that exists on testnet
	bp := common.Point{
		Slot: 74526873,
		Hash: blockHash,
	}

	b, err := connection.BlockFetch().Client.GetBlock(bp) // first call will pass
	if err != nil {
		return err
	}

	fmt.Println(b.SlotNumber(), b.Hash(), b.Transactions()) // will print some data

	connection.Close()

	_, err1 := connection.BlockFetch().Client.GetBlock(bp) // will retrieve error
	fmt.Println(err1) // this will print error "protocol is shutting down"

	_, err2 := connection.BlockFetch().Client.GetBlock(bp) // this will block
	fmt.Println(err2)

	return errors.Join(err1, err2)
}

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions