go-sqlite3 icon indicating copy to clipboard operation
go-sqlite3 copied to clipboard

signal SIGBUS: bus error

Open bjoerrrn opened this issue 3 years ago • 1 comments

Running a docker container and the docker container crashes up to 3 times a day due to the following sqlite issue.

crashing source code line:

https://github.com/mattn/go-sqlite3/blob/671e666c2e88052a814eeaed6bc8506ef326eb63/sqlite3.go#L1972

Referring to the comment "// this is still racy and can be no-op if executed between sqlite3_* calls in execSync."

The error reported refers to this function in the go implementation of sqlite… specifically line 1999.

Full example logs can be found here:

https://github.com/storj/storj/issues/4378

System Version: macOS 12.1 (21C52) Kernel Version: Darwin 21.2.0 Boot Volume: Macintosh HD Boot Mode: Normal Computer Name: xxx User Name: xxx Secure Virtual Memory: Enabled System Integrity Protection: Enabled

Hardware Overview: Model Name: Mac mini Model Identifier: Macmini9,1 Chip: Apple M1 Total Number of Cores: 8 (4 performance and 4 efficiency) Memory: 8 GB System Firmware Version: 7429.61.2 OS Loader Version: 7429.61.2 Serial Number (system): C07FF20JQ6NV Hardware UUID: xxx Provisioning UDID: xxx Activation Lock Status: Enabled

Docker version 20.10.12, build e91ed57

bjoerrrn avatar Jan 22 '22 19:01 bjoerrrn


package sqlite3

import (
	"context"
	"database/sql/driver"
	"errors"
	"sync"
)

// SQLiteStmt represents a prepared statement.
type SQLiteStmt struct {
	conn      *SQLiteConn
	stmt      *sqlite3Stmt
	args      []namedValue
	closed    bool
	mutex     sync.Mutex // Added to protect exec calls
}

// exec executes the statement with the given arguments.
func (s *SQLiteStmt) exec(ctx context.Context, args []namedValue) (driver.Result, error) {
	s.mutex.Lock()
	defer s.mutex.Unlock()

	if ctx != nil {
		select {
		case <-ctx.Done():
			return nil, ctx.Err()
		default:
		}
	}

	list := make([]namedValue, len(args))
	for i, v := range args {
		list[i] = v
	}

	var res driver.Result
	rv := C.sqlite3_reset(s.stmt)
	if rv != C.SQLITE_OK {
		return nil, s.conn.error(C.sqlite3_errmsg(s.conn.db))
	}

	for i, v := range list {
		rv = s.bind(i+1, v)
		if rv != C.SQLITE_OK {
			return nil, s.conn.error(C.sqlite3_errmsg(s.conn.db))
		}
	}

	if s.conn.isSync {
		rv = C.execSync(s.stmt, &res)
	} else {
		rv = C.sqlite3_step(s.stmt)
	}

	if rv != C.SQLITE_DONE && rv != C.SQLITE_ROW {
		err := s.conn.error(C.sqlite3_errmsg(s.conn.db))
		C.sqlite3_reset(s.stmt)
		return nil, err
	}

	if res == nil {
		var rowsAffected, lastInsertID int64
		rowsAffected = int64(C.sqlite3_changes(s.conn.db))
		last​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​

ljluestc avatar Jun 22 '25 19:06 ljluestc