Skip to content

Commit a07b6bd

Browse files
committed
Revert try_lock and temporary_table_exists patches
try_lock caused SIGSEGV from dangling stmt pointers on contention; temporary_table_exists → false caused a mid-run mutex deadlock. Both underlying issues are in Turso's upstream sqlite3 shim and can't be side-stepped here. Back to the cleanest known state: 305/667 passing, suite completes cleanly, only the shutdown deadlock remains (handled by the timeout wrapper). Remaining errors are tracked by category in the workflow — addressing them requires Turso fixes (stricter sqlite_temp_master, UPDATE row-value subquery support, sqlite3_finalize not holding sqlite3Inner across step loops).
1 parent 651fad3 commit a07b6bd

1 file changed

Lines changed: 15 additions & 86 deletions

File tree

.github/workflows/phpunit-tests-turso.yml

Lines changed: 15 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -62,61 +62,10 @@ jobs:
6262
run: |
6363
sed -i 's|todo!("{} is not implemented", stringify!($fn));|return unsafe { std::mem::zeroed() };|' sqlite3/src/lib.rs
6464
65-
# Turso's sqlite3_finalize blocks indefinitely on sqlite3Inner's
66-
# mutex during PHP shutdown. Replace .lock().unwrap() with try_lock:
67-
# on contention, skip the stmt_list cleanup (small leak) rather
68-
# than block forever. The rest of finalize (destructors, free) still
69-
# runs.
70-
python3 - <<'PY_FIN'
71-
path = 'sqlite3/src/lib.rs'
72-
src = open(path).read()
73-
old = (
74-
" if !stmt_ref.db.is_null() {\n"
75-
" let db = &mut *stmt_ref.db;\n"
76-
" let mut db_inner = db.inner.lock().unwrap();\n"
77-
"\n"
78-
" if db_inner.stmt_list == stmt {\n"
79-
" db_inner.stmt_list = stmt_ref.next;\n"
80-
" } else {\n"
81-
" let mut current = db_inner.stmt_list;\n"
82-
" while !current.is_null() {\n"
83-
" let current_ref = &mut *current;\n"
84-
" if current_ref.next == stmt {\n"
85-
" current_ref.next = stmt_ref.next;\n"
86-
" break;\n"
87-
" }\n"
88-
" current = current_ref.next;\n"
89-
" }\n"
90-
" }\n"
91-
" }\n"
92-
)
93-
new = (
94-
" if !stmt_ref.db.is_null() {\n"
95-
" let db = &mut *stmt_ref.db;\n"
96-
" // try_lock: on contention, skip stmt_list cleanup to\n"
97-
" // avoid deadlocking in PHP's GC-driven shutdown path.\n"
98-
" if let Ok(mut db_inner) = db.inner.try_lock() {\n"
99-
" if db_inner.stmt_list == stmt {\n"
100-
" db_inner.stmt_list = stmt_ref.next;\n"
101-
" } else {\n"
102-
" let mut current = db_inner.stmt_list;\n"
103-
" while !current.is_null() {\n"
104-
" let current_ref = &mut *current;\n"
105-
" if current_ref.next == stmt {\n"
106-
" current_ref.next = stmt_ref.next;\n"
107-
" break;\n"
108-
" }\n"
109-
" current = current_ref.next;\n"
110-
" }\n"
111-
" }\n"
112-
" }\n"
113-
" }\n"
114-
)
115-
assert old in src, 'finalize block not found'
116-
src = src.replace(old, new, 1)
117-
open(path, 'w').write(src)
118-
print('patched sqlite3_finalize (try_lock)')
119-
PY_FIN
65+
# (Attempted sqlite3_finalize try_lock patch caused SIGSEGV mid-run:
66+
# leaking the stmt on contention left db.stmt_list with a dangling
67+
# pointer for the next finalize to walk. Reverted. The deadlock is
68+
# handled at the CI level via `timeout` wrapping PHPUnit.)
12069
12170
python3 - <<'PY'
12271
import re
@@ -484,37 +433,17 @@ jobs:
484433
working-directory: packages/mysql-on-sqlite
485434
run: |
486435
python3 - <<'PY'
487-
# 1. Turso doesn't expose `sqlite_temp_master`. The driver queries it
488-
# to decide whether to use temp-schema tables, but Turso doesn't
489-
# support TEMP tables at all, so the predicate is always false.
490-
path = 'src/sqlite/class-wp-sqlite-information-schema-builder.php'
491-
src = open(path).read()
492-
old = (
493-
"\tpublic function temporary_table_exists( string $table_name ): bool {\n"
494-
"\t\t/*\n"
495-
"\t\t * We could search in the \"{$this->temporary_table_prefix}tables\" table,\n"
496-
"\t\t * but it may not exist yet, so using \"sqlite_temp_master\" is simpler.\n"
497-
"\t\t */\n"
498-
"\t\t$stmt = $this->connection->query(\n"
499-
"\t\t\t\"SELECT 1 FROM sqlite_temp_master WHERE type = 'table' AND name = ?\",\n"
500-
"\t\t\tarray( $table_name )\n"
501-
"\t\t);\n"
502-
"\t\treturn $stmt->fetchColumn() === '1';\n"
503-
"\t}"
504-
)
505-
new = (
506-
"\tpublic function temporary_table_exists( string $table_name ): bool {\n"
507-
"\t\treturn false; // Turso has no TEMP tables and no sqlite_temp_master.\n"
508-
"\t}"
509-
)
510-
assert old in src, 'temporary_table_exists body not found'
511-
src = src.replace(old, new, 1)
512-
open(path, 'w').write(src)
513-
print('patched information-schema-builder.php')
514-
515-
# 2. wp_die polyfill: real WordPress provides wp_die(); the unit-test
516-
# bootstrap doesn't, so 21 tests hit an 'undefined function' error
517-
# when a driver error path tries to call it.
436+
# Abandoned driver patches:
437+
# - temporary_table_exists → false triggers a Turso mid-run mutex
438+
# deadlock. Leaving the query in place; the resulting 250 errors
439+
# are preferable to an indefinite hang.
440+
# - sync_column_key_info UPDATE rewrite triggers a Turso query-
441+
# planner pathological case; similar hang.
442+
# Only the wp_die polyfill is safe (it doesn't alter query flow).
443+
444+
# wp_die polyfill: real WordPress provides wp_die(); the unit-test
445+
# bootstrap doesn't, so 21 tests hit an 'undefined function' error
446+
# when a driver error path tries to call it.
518447
path = 'tests/bootstrap.php'
519448
src = open(path).read()
520449
marker = "if ( ! function_exists( 'do_action' ) ) {"

0 commit comments

Comments
 (0)