matrixorigin / matrixone

Hyperconverged cloud-edge native database
https://docs.matrixorigin.cn/en
Apache License 2.0
1.75k stars 273 forks source link

[Bug]: nil pointer deref in frontend #17592

Closed reusee closed 1 month ago

reusee commented 1 month ago

Is there an existing issue for the same bug?

Branch Name

main

Commit ID

3659b760f3ab3516c2954a748a7e66ea527363f7

Other Environment Information

- Hardware parameters:
- OS type:
- Others:

Actual Behavior

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x58 pc=0x3856c32]

goroutine 2623 [running]:
github.com/matrixorigin/matrixone/pkg/frontend.(*Routine).getProtocol(0x558f118?)
    /home/reus/mo/panic/pkg/frontend/routine.go:146 +0x32
github.com/matrixorigin/matrixone/pkg/frontend.(*MOServer).handshake(0xc0007645b0?, 0xc02cb95ad0)
    /home/reus/mo/panic/pkg/frontend/server.go:198 +0x225
github.com/matrixorigin/matrixone/pkg/frontend.(*MOServer).handleConn(0xc01afe95f0, {0x55da998?, 0xc01b003bf8?})
    /home/reus/mo/panic/pkg/frontend/server.go:165 +0x1e5
created by github.com/matrixorigin/matrixone/pkg/frontend.(*MOServer).startAccept in goroutine 2146
    /home/reus/mo/panic/pkg/frontend/server.go:153 +0xfd

bisected to this commit: 3659b760f3ab3516c2954a748a7e66ea527363f7

Expected Behavior

No response

Steps to Reproduce

run this program, then start MO

package main

import (
    "database/sql"
    "fmt"
    "sync"
    "sync/atomic"
    "time"

    _ "github.com/go-sql-driver/mysql"
)

const (
    addr                     = "dump:111@tcp(localhost:6001)/mysql"
    numThreads               = 1024
    statementsPerTransaction = 1
)

func main() {
connect:
    db, err := sql.Open("mysql", addr)
    if err != nil {
        pt("%v\n", err)
        time.Sleep(time.Second)
        goto connect
    }
    defer db.Close()
    err = db.Ping()
    if err != nil {
        pt("%v\n", err)
        time.Sleep(time.Second)
        goto connect
    }

    _, err = db.Exec(`drop database if exists foo`)
    ce(err)
    _, err = db.Exec(`create database foo`)
    ce(err)
    _, err = db.Exec(`use foo`)
    ce(err)
    pt("database created\n")

    _, err = db.Exec(`create table foo (
    a bigint primary key,
    b bigint
  )`)
    ce(err)
    pt("table created\n")

    var counter atomic.Int64
    errStats := NewMap[string, int]()

    wg := new(sync.WaitGroup)
    wg.Add(numThreads)
    for i := 0; i < numThreads; i++ {
        go func() {
            defer wg.Done()
            start(&counter, errStats)
        }()
    }

    go func() {
        interval := time.Second * 1
        ticker := time.NewTicker(interval)
        for range ticker.C {
            n := counter.Swap(0)
            pt("%v per %v\n", n, interval)
            errStats.Lock()
            for str, n := range errStats.m {
                pt("err: %10v %v\n", n, str)
            }
            errStats.Unlock()
        }
    }()

    wg.Wait()
}

type Map[K comparable, V any] struct {
    sync.Mutex
    m map[K]V
}

func NewMap[K comparable, V any]() *Map[K, V] {
    return &Map[K, V]{
        m: make(map[K]V),
    }
}

var nextNum = new(atomic.Int64)

func start(
    counter *atomic.Int64,
    errStats *Map[string, int],
) {
    db, err := sql.Open("mysql", addr)
    ce(err)
    defer db.Close()
    ce(db.Ping())

    _, err = db.Exec(`use foo`)
    ce(err)

    for {
        counter.Add(1)

        for i := 0; i < statementsPerTransaction; i++ {
            a := nextNum.Add(1)
            b := nextNum.Add(1)
            c := nextNum.Add(1)

            res, err := db.Exec(
                `insert into foo (a, b) values (?, ?)`,
                a,
                b,
            )
            ce(err)
            n, err := res.RowsAffected()
            ce(err)
            if n != 1 {
                panic("bad")
            }

            res, err = db.Exec(
                `update foo set b = ? where a = ?`,
                c,
                a,
            )
            ce(err)
            n, err = res.RowsAffected()
            ce(err)
            if n != 1 {
                panic("bad")
            }

            var result int64
            ce(db.QueryRow(`select b from foo where a = ?`, a).Scan(&result))
            if result != c {
                panic("wrong")
            }

        }

    }
}

var pt = fmt.Printf

func ce(err error) {
    if err != nil {
        panic(err)
    }
}


### Additional information

_No response_
CJKkkk-315 commented 1 month ago

https://github.com/matrixorigin/matrixone/pull/17573 这个PR应该可以解决

CJKkkk-315 commented 1 month ago

pr合并后应该没有再出现了 可以先关闭 @reusee