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:
- Runtime crash (P0):
v_stable_sort: RUNTIME ERROR: invalid memory access— occurs whenever pool operations (create, acquire) are called withimport db.pgpresent - C compilation error (P1):
cannot convert 'struct db__mysql__DB' to 'struct db__pg__Pool *'— occurs when bothmysql.DBandpg.DBconcrete types are used as generic type arguments andacquire()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.