ClickHouse/ch-go

Possible stuck when we set big timeout

vadimalekseev opened this issue · 0 comments

Describe the bug

Stuck conn.Do(query) if we set big timeout through the context.Context

Steps to reproduce

  1. Create context with big timeout, e.g.: ctx, cancel := context.WithTimeout(context.Background(), time.Hour)
  2. Do some invalid request (check my example below)

Expected behaviour

It seems to me that we should immediately get a response from the .Do(query) function

Code example

package main

import (
	"context"
	"fmt"
	"time"

	"github.com/ClickHouse/ch-go"
	"github.com/ClickHouse/ch-go/chpool"
	"github.com/ClickHouse/ch-go/proto"
)

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), time.Hour)
	defer cancel()

	conn, err := chpool.Dial(ctx, chpool.Options{
		ClientOptions: ch.Options{
			Address: "127.0.0.1:9001",
		},
	})
	if err != nil {
		panic(err)
	}

	err = conn.Do(ctx, ch.Query{Body: `DROP TABLE IF EXISTS test_table_insert`})
	if err != nil {
		panic(err)
	}

	err = conn.Do(ctx, ch.Query{
		Body: `CREATE TABLE IF NOT EXISTS test_table_insert
(
    level Enum8('error'=1, 'warn'=2, 'info'=3, 'debug'=4)
) ENGINE = Memory;`})
	if err != nil {
		panic(err)
	}

	level := new(proto.ColEnum)
	err = level.Infer("Enum8('error'=1, 'warn'=2, 'info'=3, 'debug'=4)")
	if err != nil {
		panic(err)
	}

	level.Append("unknown level") // ! this level does not exist in the enum

	err = conn.Do(ctx, ch.Query{
		Body: `INSERT INTO test_table_insert VALUES`,
		Input: proto.Input{
			{Name: "level", Data: level},
		},
	}) // lock here for an 1 hour
	if err != nil {
		panic(err)
	}

	fmt.Println("done")
}

Some parts of the goroutines dump:

1 @ 0x100a74e14 0x100a41b04 0x100a41674 0x100f64da4 0x100f5c7ec 0x100aa6334
#	0x100f64da3	github.com/ClickHouse/ch-go.(*Client).Do.func5+0x43	/Users/valekseev/go/pkg/mod/github.com/!click!house/ch-go@v0.52.0/query.go:688
#	0x100f5c7eb	golang.org/x/sync/errgroup.(*Group).Go.func1+0x5b	/Users/valekseev/go/pkg/mod/golang.org/x/sync@v0.0.0-20220923202941-7f9b1623fab7/errgroup/errgroup.go:75



1 @ 0x100a74e14 0x100a6dfd8 0x100aa00d0 0x100ada4e8 0x100adb810 0x100adb801 0x100cb97d8 0x100ccac04 0x100b51020 0x100ed677c 0x100ad56f0 0x100ed685c 0x100ed683d 0x100ed65f4 0x100ed65f5 0x100b76bb0 0x100ed6a48 0x100f5d4b4 0x100f64f40 0x100f5c7ec 0x100aa6334
#	0x100aa00cf	internal/poll.runtime_pollWait+0x9f				/opt/homebrew/Cellar/go/1.19.2/libexec/src/runtime/netpoll.go:305
#	0x100ada4e7	internal/poll.(*pollDesc).wait+0x27				/opt/homebrew/Cellar/go/1.19.2/libexec/src/internal/poll/fd_poll_runtime.go:84
#	0x100adb80f	internal/poll.(*pollDesc).waitRead+0x1df			/opt/homebrew/Cellar/go/1.19.2/libexec/src/internal/poll/fd_poll_runtime.go:89
#	0x100adb800	internal/poll.(*FD).Read+0x1d0					/opt/homebrew/Cellar/go/1.19.2/libexec/src/internal/poll/fd_unix.go:167
#	0x100cb97d7	net.(*netFD).Read+0x27						/opt/homebrew/Cellar/go/1.19.2/libexec/src/net/fd_posix.go:55
#	0x100ccac03	net.(*conn).Read+0x33						/opt/homebrew/Cellar/go/1.19.2/libexec/src/net/net.go:183
#	0x100b5101f	bufio.(*Reader).Read+0x1df					/opt/homebrew/Cellar/go/1.19.2/libexec/src/bufio/bufio.go:237
#	0x100ed677b	github.com/ClickHouse/ch-go/proto.(*Reader).Read+0x2b		/Users/valekseev/go/pkg/mod/github.com/!click!house/ch-go@v0.52.0/proto/reader.go:53
#	0x100ad56ef	io.ReadAtLeast+0x9f						/opt/homebrew/Cellar/go/1.19.2/libexec/src/io/io.go:332
#	0x100ed685b	io.ReadFull+0x3b						/opt/homebrew/Cellar/go/1.19.2/libexec/src/io/io.go:351
#	0x100ed683c	github.com/ClickHouse/ch-go/proto.(*Reader).ReadFull+0x1c	/Users/valekseev/go/pkg/mod/github.com/!click!house/ch-go@v0.52.0/proto/reader.go:62
#	0x100ed65f3	github.com/ClickHouse/ch-go/proto.(*Reader).readFull+0xb3	/Users/valekseev/go/pkg/mod/github.com/!click!house/ch-go@v0.52.0/proto/reader.go:70
#	0x100ed65f4	github.com/ClickHouse/ch-go/proto.(*Reader).ReadByte+0xb4	/Users/valekseev/go/pkg/mod/github.com/!click!house/ch-go@v0.52.0/proto/reader.go:36
#	0x100b76baf	encoding/binary.ReadUvarint+0x7f				/opt/homebrew/Cellar/go/1.19.2/libexec/src/encoding/binary/varint.go:133
#	0x100ed6a47	github.com/ClickHouse/ch-go/proto.(*Reader).UVarInt+0x27	/Users/valekseev/go/pkg/mod/github.com/!click!house/ch-go@v0.52.0/proto/reader.go:84
#	0x100f5d4b3	github.com/ClickHouse/ch-go.(*Client).packet+0x113		/Users/valekseev/go/pkg/mod/github.com/!click!house/ch-go@v0.52.0/client.go:224
#	0x100f64f3f	github.com/ClickHouse/ch-go.(*Client).Do.func4+0xff		/Users/valekseev/go/pkg/mod/github.com/!click!house/ch-go@v0.52.0/query.go:657
#	0x100f5c7eb	golang.org/x/sync/errgroup.(*Group).Go.func1+0x5b		/Users/valekseev/go/pkg/mod/golang.org/x/sync@v0.0.0-20220923202941-7f9b1623fab7/errgroup/errgroup.go:75

Researching brought me to the function func (c *Client) packet(ctx context.Context) (proto.ServerCode, error)

-- we check and override the default timeout from the context:

	deadline := time.Now().Add(defaultTimeout)
	if d, ok := ctx.Deadline(); ok {
		deadline = d
	}

Therefore, we have come out of this function for so long, so the done (/ch-go@v0.52.0/query.go:688) channel does not close, so we cannot get an answer.

Configuration

Environment

  • Client version: v0.52.0
  • Language version: 1.19

ClickHouse server

  • ClickHouse Server version: 22.1.3.7