vlang

/

v Public
0 commits 39 issues 0 pull requests 0 contributors Discussions Projects CI

Generic Pool with db.mysql + db.pg causes v_stable_sort runtime crash or C code generation failure #17

Describe the bug

When a generic struct implements an interface and its methods use conn as T to extract a connection from pool.ConnectionPool, having both db.mysql and db.pg imported and used as type parameter T in the same module causes two distinct failures:

  1. Runtime crash (P0): v_stable_sort: RUNTIME ERROR: invalid memory access — occurs whenever pool operations (create, acquire) are called with import db.pg present
  2. C compilation error (P1): cannot convert 'struct db__mysql__DB' to 'struct db__pg__Pool *' — occurs when both mysql.DB and pg.DB concrete types are used as generic type arguments and acquire() is actually called

Reproduction (runtime crash)

Single file: check/pool_bug.v in the attached project, or:

# Requires MySQL on 127.0.0.1:3306 (root/mysql_123456/vcore)
# Requires PostgreSQL on 127.0.0.1:5432 (root/pg_123456/vcore)
git clone https://github.com/Jengro777/RuoQi-v.git
cd RuoQi-v/backend
v run check/pool_bug.v

Expected output:

v_stable_sort: RUNTIME ERROR: invalid memory access

Workaround

Remove import db.pg and PG-related code. MySQL-only generic pool works correctly.

Suspected cause

import db.pg brings in libpq C symbols that interfere with V's pool module internal memory management. The pool module's v_stable_sort function accesses corrupted heap memory when PG symbols are present in the same compilation unit.

The C compilation error (P1) suggests V's C code generator doesn't properly distinguish type instantiations when the same generic method handles both mysql.DB and pg.DB.

Reproduction Steps

module main

import orm
import pool
import db.mysql
import db.pg

interface Poolable {
mut:
    acquire() !(orm.Connection, &pool.ConnectionPoolable)
    close()
}

@[heap]
struct Pool[T] implements Poolable {
pub mut:
    inner &pool.ConnectionPool
}

fn new_mysql_pool() !&Pool[mysql.DB] {
    cfg := ''
    create_conn := fn [cfg] () !&pool.ConnectionPoolable {
        _ = cfg
        mut db := mysql.connect(mysql.Config{
            host:     '127.0.0.1'
            port:     3306
            username: 'root'
            password: 'mysql_123456'
            dbname:   'vcore'
        })!
        return &db
    }
    p := pool.new_connection_pool(create_conn, pool.ConnectionPoolConfig{
        max_conns:      1
        min_idle_conns: 0
    })!
    return &Pool[mysql.DB]{
        inner: p
    }
}

fn new_pg_pool() !&Pool[pg.DB] {
    cfg := ''
    create_conn := fn [cfg] () !&pool.ConnectionPoolable {
        _ = cfg
        mut db := pg.connect(pg.Config{
            host:     '127.0.0.1'
            port:     5432
            username: 'root'
            password: 'pg_123456'
            dbname:   'vcore'
        }, pg.PoolConfig{})!
        return &db
    }
    p := pool.new_connection_pool(create_conn, pool.ConnectionPoolConfig{
        max_conns:      1
        min_idle_conns: 0
    })!
    return &Pool[pg.DB]{
        inner: p
    }
}

fn (mut p Pool[T]) acquire() !(orm.Connection, &pool.ConnectionPoolable) {
    conn := p.inner.get()!
    return conn as T, conn
}

fn (mut p Pool[T]) close() {
    p.inner.close()
}

fn main() {
    mut p := new_mysql_pool() or { return }
    _, _ := p.acquire() or { return }
    p.close()

    mut q := new_pg_pool() or { return }
    _, _ := q.acquire() or { return }
    q.close()
}

v run main.v

Expected Behavior

success

Current Behavior

Fatal glibc error: tpp.c:83 (__pthread_tpp_change_priority): assertion failed: new_prio == -1 || (new_prio >= fifo_min_prio && new_prio <= fifo_max_prio)
0x70a20547518c: at ???: RUNTIME ERROR: abort() called
0x70a2048f5320: by ???
0x70a2048f5320: by ???
0x70a2048f5320: by ???
0x70a2048f5320: by ???
0x70a2048f5320: by ???
0x70a2048f5320: by ???
0x70a2048f5320: by ???
0x70a2048f5320: by ???
0x70a2048f5320: by ???
0x70a2048f5320: by ???
0x70a2048f5320: by ???
0x70a2048f5320: by ???
0x70a2048f5320: by ???
0x70a2048f5320: by ???
0x70a2048f5320: by ???
0x70a2048f5320: by ???
0x70a2048f5320: by ???
0x70a2048f5320: by ???
0x70a2048f5320: by ???
0x70a2048f5320: by ???
0x70a2048f5320: by ???
0x70a2048f5320: by ???
0x70a2048f5320: by ???
0x70a2048f5320: by ???

Possible Solution

No response

Additional Information/Context

No response

V version

V 0.5.1 3690f88

Environment details (OS name and version, etc.)

|V full version |V 0.5.1 e4a265a9914ea9ccb947436b277c31362141c90d.3690f88 |:-------------------|:------------------- |OS |linux, Deepin 25 |Processor |20 cpus, 64bit, little endian, 13th Gen Intel(R) Core(TM) i5-13500 |Memory |6.42GB/31.02GB | | |V executable |/home/Jengro/opt/v/v |V last modified time|2026-06-10 08:18:59 | | |V home dir |OK, value: /home/Jengro/opt/v |VMODULES |OK, value: /home/Jengro/.vmodules |VTMP |OK, value: /tmp/v_1000 |Current working dir |OK, value: /home/Jengro | | |Git version |git version 2.51.0 |V git status |0.5.1-1879-g3690f882 |.git/config present |true | | |cc version |cc (Deepin 12.3.0-17deepin17) 12.3.0 |gcc version |gcc (Deepin 12.3.0-17deepin17) 12.3.0 |clang version |Deepin clang version 17.0.6 (5deepin7) |tcc version |tcc version 0.9.28rc 2025-02-13 HEAD@f8bd136d (x86_64 Linux) |tcc git status |thirdparty-linux-amd64 696c1d84 |emcc version |N/A |glibc version |ldd (Debian GLIBC 2.38-6deepin24) 2.38

[!NOTE] You can use the 👍 reaction to increase the issue's priority for developers.

Please note that only the 👍 reaction to the issue itself counts as a vote. Other reactions and those to comments will not be taken into account.