You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Just ran into this on #510 (but can't reproduce it easily):
Warning 1: GPKG: bad application_id=0x00000000 on '/tmp/.tmpgi6DfV.gpkg'
ERROR 1: Layer new already exists, CreateLayer failed.
Use the layer creation option OVERWRITE=YES to replace it.
test spatial_ref::srs::tests::predicats_epsg2154 ... ok
test spatial_ref::srs::tests::get_units_epsg4326 ... ok
test spatial_ref::srs::tests::non_existing_proj_param ... ok
test vector::layer::tests::test_create_layer_options ... ok
error: test failed, to rerun pass `--lib`
Caused by:
process didn't exit successfully: `/home/grayshade/Projects/georust/gdal/target/debug/deps/gdal-0978520db0adc3dd` (signal: 11, SIGSEGV: invalid memory reference)
That looks like a temporary file name, not sure what's going on.
Oh yeah, I ran into it once as well. It passed the next time I ran it, though. Maybe, like it said, the temp filename was coincidently the same as last time the test was done, and the file isn't cleared?
Been a while since I've seen this. I'd start with checking to ensure any test that mutates an on-disk fixture is using the TempFixture tooling, so as to work on separate copies of the file.
Hmm, I was able to reproduce the crash on master, so it's not #510. The "Layer new already exists" message points to the poly.gpkg tests, which we should fix.
However, running cargo test vector in a loop doesn't seem to crash, so it's still possible that the SIGSEGV is unrelated.
#0 0x00007ffff768dfcb in OGR2SQLITEModule::Setup(sqlite3*) () from /lib64/libgdal.so.33
#1 0x00007ffff768e7d5 in OGR2SQLITE_Setup(GDALDataset*, OGRSQLiteDataSource*) () from /lib64/libgdal.so.33
#2 0x00007ffff797d9fb in OGRSQLiteDataSource::OpenOrCreateDB(int, bool) [clone .constprop.0] () from /lib64/libgdal.so.33
#3 0x00007ffff7656825 in OGRSQLiteDataSource::Open(GDALOpenInfo*) () from /lib64/libgdal.so.33
#4 0x00007ffff7677bd4 in OGRSQLiteDriverOpen(GDALOpenInfo*) () from /lib64/libgdal.so.33
#5 0x00007ffff781a4e7 in GDALOpenEx () from /lib64/libgdal.so.33
#6 0x00007ffff73065e5 in RasterliteDataset::Open(GDALOpenInfo*) () from /lib64/libgdal.so.33
#7 0x00007ffff781a4e7 in GDALOpenEx () from /lib64/libgdal.so.33
#8 0x0000555555672295 in gdal::dataset::Dataset::_open_ex (path=..., options=...) at src/dataset.rs:148
#9 0x00005555556d8adb in gdal::dataset::Dataset::open<std::path::PathBuf> (path=...) at src/dataset.rs:61
#10 0x00005555556ef76e in gdal::vector::layer::tests::ds_with_layer<gdal::vector::layer::tests::test_field_in_layer::{closure_env#0}> (ds_name=..., layer_name=..., f=...) at src/vector/layer.rs:745
#11 0x00005555557010ee in gdal::vector::layer::tests::test_field_in_layer () at src/vector/layer.rs:1164
#12 0x00005555556f7b87 in gdal::vector::layer::tests::test_field_in_layer::{closure#0} () at src/vector/layer.rs:1163
#13 0x00005555556afe46 in core::ops::function::FnOnce::call_once<gdal::vector::layer::tests::test_field_in_layer::{closure_env#0}, ()> () at /rustc/0e09125c6c3c2fd70d7de961bcf0e51575235fad/library/core/src/ops/function.rs:250
#14 0x00005555557577df in core::ops::function::FnOnce::call_once<fn() -> core::result::Result<(), alloc::string::String>, ()> () at library/core/src/ops/function.rs:250
#15 test::__rust_begin_short_backtrace<core::result::Result<(), alloc::string::String>, fn() -> core::result::Result<(), alloc::string::String>> () at library/test/src/lib.rs:627
#16 0x0000555555756561 in test::run_test_in_process::{closure#0} () at library/test/src/lib.rs:650
#17 core::panic::unwind_safe::{impl#23}::call_once<core::result::Result<(), alloc::string::String>, test::run_test_in_process::{closure_env#0}> () at library/core/src/panic/unwind_safe.rs:272
#18 std::panicking::try::do_call<core::panic::unwind_safe::AssertUnwindSafe<test::run_test_in_process::{closure_env#0}>, core::result::Result<(), alloc::string::String>> () at library/std/src/panicking.rs:552
#19 std::panicking::try<core::result::Result<(), alloc::string::String>, core::panic::unwind_safe::AssertUnwindSafe<test::run_test_in_process::{closure_env#0}>> () at library/std/src/panicking.rs:516
#20 std::panic::catch_unwind<core::panic::unwind_safe::AssertUnwindSafe<test::run_test_in_process::{closure_env#0}>, core::result::Result<(), alloc::string::String>> () at library/std/src/panic.rs:142
#21 test::run_test_in_process () at library/test/src/lib.rs:650
#22 test::run_test::{closure#0} () at library/test/src/lib.rs:573
#23 0x000055555571b416 in test::run_test::{closure#1} () at library/test/src/lib.rs:601
#24 std::sys_common::backtrace::__rust_begin_short_backtrace<test::run_test::{closure_env#1}, ()> () at library/std/src/sys_common/backtrace.rs:155
#25 0x0000555555720477 in std::thread::{impl#0}::spawn_unchecked_::{closure#1}::{closure#0}<test::run_test::{closure_env#1}, ()> () at library/std/src/thread/mod.rs:529
#26 core::panic::unwind_safe::{impl#23}::call_once<(), std::thread::{impl#0}::spawn_unchecked_::{closure#1}::{closure_env#0}<test::run_test::{closure_env#1}, ()>> () at library/core/src/panic/unwind_safe.rs:272
#27 std::panicking::try::do_call<core::panic::unwind_safe::AssertUnwindSafe<std::thread::{impl#0}::spawn_unchecked_::{closure#1}::{closure_env#0}<test::run_test::{closure_env#1}, ()>>, ()> () at library/std/src/panicking.rs:552
#28 std::panicking::try<(), core::panic::unwind_safe::AssertUnwindSafe<std::thread::{impl#0}::spawn_unchecked_::{closure#1}::{closure_env#0}<test::run_test::{closure_env#1}, ()>>> () at library/std/src/panicking.rs:516
#29 std::panic::catch_unwind<core::panic::unwind_safe::AssertUnwindSafe<std::thread::{impl#0}::spawn_unchecked_::{closure#1}::{closure_env#0}<test::run_test::{closure_env#1}, ()>>, ()> () at library/std/src/panic.rs:142
#30 std::thread::{impl#0}::spawn_unchecked_::{closure#1}<test::run_test::{closure_env#1}, ()> () at library/std/src/thread/mod.rs:528
#31 core::ops::function::FnOnce::call_once<std::thread::{impl#0}::spawn_unchecked_::{closure_env#1}<test::run_test::{closure_env#1}, ()>, ()> () at library/core/src/ops/function.rs:250
#32 0x00005555557a3cf5 in alloc::boxed::{impl#47}::call_once<(), dyn core::ops::function::FnOnce<(), Output=()>, alloc::alloc::Global> () at library/alloc/src/boxed.rs:2015
#33 alloc::boxed::{impl#47}::call_once<(), alloc::boxed::Box<dyn core::ops::function::FnOnce<(), Output=()>, alloc::alloc::Global>, alloc::alloc::Global> () at library/alloc/src/boxed.rs:2015
#34 std::sys::unix::thread::{impl#2}::new::thread_start () at library/std/src/sys/unix/thread.rs:108
#35 0x00007ffff65cb897 in start_thread () from /lib64/libc.so.6
#36 0x00007ffff66526fc in clone3 () from /lib64/libc.so.6
Caught it with while gdb -ex=r -ex=quit --args target/debug/deps/gdal-0978520db0adc3dd; end.
Am I right that both proj and gpkg use SQLite? If so, I wonder if there's any chance one of them was compiled with a different version than the other? 🤷 Shooting in the dark here.
CC @rouault I don't know if I can reproduce this in pure GDAL. It might be a race on our side between GDALAllRegister and e.g. OSRImportFromEPSG. Or maybe there's something fishy going on around OGR2SQLITE_Register.
@lnicola I've tried to reproduce on my system using GDAL master and SQLite 3.31.4 (ubuntu 20.04), but target/release/deps/gdal-fcd32cea6720c7b7 "-q" "--test-threads" "2" "vector::layer::tests::test_field_in_layer" "vector::layer::tests::test_create_layer_options" "spatial_ref::transform_opts::tests::set_coordinate_operation" runs fine for me.
What could help perhaps is if you could add the following debug trace to your GDAL build:
Extermely weird. I don't see how that happen. Even if OGR2SQLITE_static_register() was called with _pApi == nullptr (which can only happen if SQLite is built with SQLITE_OMIT_LOAD_EXTENSION), then the following will assign default pointers:
We only call GDALAllRegister from a single thread (using something like call_once. I'm not sure what kind of ordering it uses, but one possibility is that sqlite3_api is initialized on one thread, while another one sees it as null. That's likely to just initialize it twice, but..
The other possibility is that it's racing against libproj's usage of SQLite. Though it seems less likely (I didn't check, but I assume it's not setting itself up as an extension or anything weird like that).
I added that debug-print (with the thread id too) and the result was not what I expected:
Successful run:
running 4 tests
Warning 1: GPKG: bad application_id=0x00000000 on '/tmp/.tmpPailY2.gpkg'
ERROR 1: Layer new already exists, CreateLayer failed.
Use the layer creation option OVERWRITE=YES to replace it.
.[0x7f04e39566c0] pApi=0x7f05ea1faee0, pApi->create_module = 0x7f05ea149a30, pApi->create_module_v2 = 0x7f05ea149a40
ERROR 1: PROJ: hgridshift: could not find required grid(s).
ERROR 1: PROJ: pipeline: Pipeline: Bad step definition: proj=hgridshift (File not found or invalid)
.[0x7f04e39566c0] pApi=0x7f05ea1faee0, pApi->create_module = 0x7f05ea149a30, pApi->create_module_v2 = 0x7f05ea149a40
.ERROR 6: Cannot find coordinate operations from `EPSG:6491' to `EPSG:28992'
.
test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 261 filtered out; finished in 0.04s
Failed run:
running 4 tests
Warning 1: GPKG: bad application_id=0x00000000 on '/tmp/.tmpVbt6oy.gpkg'
ERROR 1: Layer new already exists, CreateLayer failed.
Use the layer creation option OVERWRITE=YES to replace it.
ERROR 1: PROJ: hgridshift: could not find required grid(s).
ERROR 1: PROJ: pipeline: Pipeline: Bad step definition: proj=hgridshift (File not found or invalid)
..fish: Job 1, 'target/release/deps/gdal-a5f1a0…' terminated by signal SIGSEGV (Address boundary error)
(tested on GDAL 3.7.3 with SQLite 3.42.0)
To reproduce:
$ DEBUGINFOD_URLS=https://debuginfod.fedoraproject.org/ LD_LIBRARY_PATH=~/Projects/gdal/install/lib64 GDAL_INCLUDE_DIR=~/Projects/gdal/install/include GDAL_LIB_DIR=~/Projects/gdal/install/lib64 GDAL_VERSION=3.7.3 GDAL_HOME=~/Projects/gdal/install/share while gdb -ex="set debuginfod enabled on" -ex=r -ex=quit --args target/release/deps/gdal-a5f1a0f14e3eca4c -q --test-threads 3 -- spatial_ref::transform_opts::tests::set_coordinate_operation spatial_ref::transform_opts::tests::invalid_transformation vector::layer::tests::test_create_layer_options vector::layer::tests::test_field_in_layer; end
# or
LD_LIBRARY_PATH=~/Projects/gdal/install/lib64 GDAL_INCLUDE_DIR=~/Projects/gdal/install/include GDAL_LIB_DIR=~/Projects/gdal/install/lib64 GDAL_VERSION=3.7.3 GDAL_HOME=~/Projects/gdal/install/share while target/release/deps/gdal-a5f1a0f14e3eca4c -q --test-threads 3 -- spatial_ref::transform_opts::tests::set_coordinate_operation spatial_ref::transform_opts::tests::invalid_transformation vector::layer::tests::test_create_layer_options vector::layer::tests::test_field_in_layer; end
(for POSIX shells that should be while ...;do done or something like that, and target/release/deps/gdal-a5f1a0f14e3eca4c is from the output of cargo test --release)
running 4 tests
Warning 1: GPKG: bad application_id=0x00000000 on '/tmp/.tmp3pxmLj.gpkg'
ERROR 1: Layer new already exists, CreateLayer failed.
Use the layer creation option OVERWRITE=YES to replace it.
.[0x7f9e04f566c0] OGR2SQLITE_Register: entry
[0x7f9e04f566c0] OGR2SQLITE_Register: exit, sqlite3_auto_extension() -> 0
[0x7f9e04f566c0] OGR2SQLITE_static_register pApi=0x7f9f0bd60ee0, pApi->create_module = 0x7f9f0bcafa30, pApi->create_module_v2 = 0x7f9f0bcafa40
[0x7f9e04f566c0] OGR2SQLITEModule::Setup, sqlite3_api = 0x7f9f0bd60ee0
ERROR 1: PROJ: hgridshift: could not find required grid(s).
ERROR 1: PROJ: pipeline: Pipeline: Bad step definition: proj=hgridshift (File not found or invalid)
.[0x7f9e04f566c0] OGR2SQLITE_Register: entry
[0x7f9e04f566c0] OGR2SQLITE_Register: exit, sqlite3_auto_extension() -> 0
[0x7f9e04f566c0] OGR2SQLITE_static_register pApi=0x7f9f0bd60ee0, pApi->create_module = 0x7f9f0bcafa30, pApi->create_module_v2 = 0x7f9f0bcafa40
[0x7f9e04f566c0] OGR2SQLITEModule::Setup, sqlite3_api = 0x7f9f0bd60ee0
.ERROR 6: Cannot find coordinate operations from `EPSG:6491' to `EPSG:28992'
running 4 tests
Warning 1: GPKG: bad application_id=0x00000000 on '/tmp/.tmpyoCohp.gpkg'
ERROR 1: Layer new already exists, CreateLayer failed.
Use the layer creation option OVERWRITE=YES to replace it.
ERROR 1: PROJ: hgridshift: could not find required grid(s).
ERROR 1: PROJ: pipeline: Pipeline: Bad step definition: proj=hgridshift (File not found or invalid)
.[0x7f6bb75576c0] OGR2SQLITE_Register: entry
[0x7f6bb75576c0] OGR2SQLITE_Register: exit, sqlite3_auto_extension() -> 0
.[0x7f6bb75576c0] OGR2SQLITEModule::Setup, sqlite3_api = (nil)
fish: Job 1, 'target/release/deps/gdal-a5f1a0…' terminated by signal SIGSEGV (Address boundary error)
So, without having looked in detail at the rest of the code:
we call GDALAllRegisterOGRSQLiteBaseDataSource::OpenOrCreateDB -> OGR2SQLITE_Register -> sqlite3_auto_extension from , which stores the pointer for later
sqlite3_open calls openDatabase, which calls all extensions via sqlite3AutoLoadExtensions
our extension (OGR2SQLITE_static_register) should initialize sqlite3_api but doesn't get called
OGR2SQLITEModule::Setup tries to call sqlite3_api->sqlite3_create_module_v2, but gets a NULL
I still don't manage to reproduce within a fedora:39 Docker image, even while looping for ever.
I've been digging into sqlite3 code source, and one very slightly suspicious thing is this optimization in sqlite3AutoLoadExtensions(): https://github.com/sqlite/sqlite/blob/89efa897780db03eac974eb6b0e041cfb7c39733/src/loadext.c#L873 , where wsdAutoext.nExt is tested against 0 outside of the SQLITE_MUTEX_STATIC_MAIN mutex that is normally used otherwise. But this does still seem OK given my understanding of multithreading and mutexes.
My hypothesis to explain what you observe would be:
thread A does PROJ stuff which opens proj.db, which calls sqlite3AutoLoadExtensions() and sees wsdAutoext.nExt == 0 (OGR2SQLITE_Register() having not yet been called)
thread B calls OGRSQLiteDataSource::OpenOrCreateDB(..., 1), which calls OGR2SQLITE_Register(), which calls sqlite3_auto_extension(), which sets wsdAutoext.nExt = 1, but within the mutex
thread B opens a sqlite3 database, which calls sqlite3AutoLoadExtensions(), but for a reason I don't understand, it would still see the value of wsdAutoext.nExt == 0 that was seen by thread A, instead of the value 1 set previously under the mutex by thread B. But I don't think that's possible... Anyway thinking out loud in case as I've no better idea. (another possibility would be that some code would call sqlite3_reset_auto_extension(), which has the effect of reseting wsdAutoext.nExt to 0, but neither GDAL nor PROJ do that)
I don't know if I can add something valuable to the dscussion, but we've recently added cargo as a dependency and our test suite ran with 0.76 but with 0.77 (geo-engine/geoengine#929) one GdalOpenEx call with georust/gdal suddenly had a SIGSEGV.
Looking at this thread I noticed that 0.77 got a dependency of rusqlite, which again brought libsqlite3-sys=0.28. Removing this dependency seemed to remove the SIGSEGV… which is very scary.
// Unlikely to happen. One theoretical possibility would be that:
// - thread A calls OGR2SQLITE_Register(), which calls sqlite3_auto_extension((void (*)(void))OGR2SQLITE_static_register)
// - thread B calls sqlite3_reset_auto_extension()
// - thread A opens a sqlite3 handle (which normally would have caused OGR2SQLITE_static_register() to be called, and setting the sqlite3_api static variable, without prior B intervention.
// - thread A calls us (OGR2SQLITE_Setup()) with sqlite3_api still set to its initial nullptr value
However, OGRSQLiteBaseDataSource::FinishSpatialite() calls spatialite_cleanup_ex, which does sqlite3_reset_auto_extension, so it's actually pretty easy to trigger. That can prevent OGR2SQLITE_static_register from getting called until the next OGR2SQLITE_Register.
Activity
Atreyagaurav commentedon Jan 10, 2024
Oh yeah, I ran into it once as well. It passed the next time I ran it, though. Maybe, like it said, the temp filename was coincidently the same as last time the test was done, and the file isn't cleared?
lnicola commentedon Jan 10, 2024
No, they're checked for collisions.
Not saying it's because of your changes, I just didn't see it before.
metasim commentedon Jan 11, 2024
Been a while since I've seen this. I'd start with checking to ensure any test that mutates an on-disk fixture is using the
TempFixturetooling, so as to work on separate copies of the file.lnicola commentedon Jan 11, 2024
Hmm, I was able to reproduce the crash on
master, so it's not #510. The "Layer new already exists" message points to thepoly.gpkgtests, which we should fix.However, running
cargo test vectorin a loop doesn't seem to crash, so it's still possible that the SIGSEGV is unrelated.lnicola commentedon Jan 11, 2024
Caught it with
while gdb -ex=r -ex=quit --args target/debug/deps/gdal-0978520db0adc3dd; end.metasim commentedon Jan 11, 2024
Great tip!
Am I right that both
projandgpkguse SQLite? If so, I wonder if there's any chance one of them was compiled with a different version than the other? 🤷 Shooting in the dark here.lnicola commentedon Jan 11, 2024
They should be dynamically linked. I think SQLite is pretty robust, at least in some build configurations (unlike.. ahem.. netcdf).
And I couldn't trigger it when filtering by
layers(or anything else), so it might be interference from am unrelated test. Maybe even from proj.lnicola commentedon Jan 12, 2024
I still had gdb running, so I checked the other threads:
So indeed, it looks like proj is also calling into SQLite at the same time, not that it proves anything.
EDIT: another one, this time with debug symbols:
The crash is at:
So https://github.com/OSGeo/gdal/blob/6133cf34a78077998406c0c4045bf51f06e3f49d/ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.cpp#L2611 looks just about right.
However,
%raxis 0:So it looks like the
sqlite3_create_module_v2call is pointing nowhere, but I don't understand why.lnicola commentedon Jan 12, 2024
CC @rouault I don't know if I can reproduce this in pure GDAL. It might be a race on our side between
GDALAllRegisterand e.g.OSRImportFromEPSG. Or maybe there's something fishy going on aroundOGR2SQLITE_Register.I managed to reproduce this using 3 tests:
Anyway, taking a closer look at the assembly,
_ZL11sqlite3_api.lto_priv.0is NULL. That's a LTO-mangled name forsqlite3_api, from https://github.com/OSGeo/gdal/blob/6133cf34a78077998406c0c4045bf51f06e3f49d/ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.cpp#L135.That seems to be initialized through
OGR2SQLITE_Register(weird cast there) at https://github.com/OSGeo/gdal/blob/6133cf34a78077998406c0c4045bf51f06e3f49d/ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.cpp#L2760C5-L2760C27 (the macro expands tosqlite3_api = pApi).But the stack trace has:
So
OGRSQLiteDataSource::OpenOrCreateDB(..., true)should have already calledOGRSQLiteBaseDataSource::OpenOrCreateDBandOGR2SQLITE_Register, ending up at https://github.com/OSGeo/gdal/blob/6133cf34a78077998406c0c4045bf51f06e3f49d/ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp#L1294. This is all on the same thread.I don't really understand how this is happening, but it's probably caused by that
sqlite3_apiglobal.metasim commentedon Jan 12, 2024
Wow, nice work, and nice case study in using
gdbwith mixed language debugging! Thanks for sharing your process!lnicola commentedon Jan 12, 2024
https://sqlite.org/src/file?name=src/sqlite3ext.h
Right, well that explains the indirect call in the asm 🤦♂️.
rouault commentedon Jan 12, 2024
@lnicola I've tried to reproduce on my system using GDAL master and SQLite 3.31.4 (ubuntu 20.04), but
target/release/deps/gdal-fcd32cea6720c7b7 "-q" "--test-threads" "2" "vector::layer::tests::test_field_in_layer" "vector::layer::tests::test_create_layer_options" "spatial_ref::transform_opts::tests::set_coordinate_operation"runs fine for me.What could help perhaps is if you could add the following debug trace to your GDAL build:
lnicola commentedon Jan 12, 2024
Will try, I have to build it first.
It's not too easy to reproduce, I was continuously running that in a loop, over 10 to 20 instances, and it still took a couple of minutes.
In any case, in my crash it's
sqlite3_apithat's null, not thecreate_module_v2pointer.rouault commentedon Jan 12, 2024
Extermely weird. I don't see how that happen. Even if OGR2SQLITE_static_register() was called with _pApi == nullptr (which can only happen if SQLite is built with SQLITE_OMIT_LOAD_EXTENSION), then the following will assign default pointers:
And sqlite3_api is declared static at line 144 (
static SQLITE_EXTENSION_INIT1), so I don't see what could mess it up behind our backlnicola commentedon Jan 12, 2024
We only call
GDALAllRegisterfrom a single thread (using something likecall_once. I'm not sure what kind of ordering it uses, but one possibility is thatsqlite3_apiis initialized on one thread, while another one sees it as null. That's likely to just initialize it twice, but..lnicola commentedon Jan 12, 2024
The other possibility is that it's racing against libproj's usage of SQLite. Though it seems less likely (I didn't check, but I assume it's not setting itself up as an extension or anything weird like that).
lnicola commentedon Jan 13, 2024
I added that debug-print (with the thread id too) and the result was not what I expected:
Successful run:
Failed run:
(tested on GDAL 3.7.3 with SQLite 3.42.0)
To reproduce:
(for POSIX shells that should be
while ...;do doneor something like that, andtarget/release/deps/gdal-a5f1a0f14e3eca4cis from the output ofcargo test --release)lnicola commentedon Jan 13, 2024
With more logging:
So, without having looked in detail at the rest of the code:
GDALAllRegisterOGRSQLiteBaseDataSource::OpenOrCreateDB->OGR2SQLITE_Register->sqlite3_auto_extensionfrom , which stores the pointer for latersqlite3_opencallsopenDatabase, which calls all extensions viasqlite3AutoLoadExtensionsOGR2SQLITE_static_register) should initializesqlite3_apibut doesn't get calledOGR2SQLITEModule::Setuptries to callsqlite3_api->sqlite3_create_module_v2, but gets a NULLrouault commentedon Jan 13, 2024
OGR2SQLITE_Register is only called by OGRSQLiteBaseDataSource::OpenOrCreateDB(), not at GDALAllRegister() time
lnicola commentedon Jan 13, 2024
Of course, not sure what I was seeing. With more logging
rouault commentedon Jan 13, 2024
I still don't manage to reproduce within a fedora:39 Docker image, even while looping for ever.
I've been digging into sqlite3 code source, and one very slightly suspicious thing is this optimization in sqlite3AutoLoadExtensions(): https://github.com/sqlite/sqlite/blob/89efa897780db03eac974eb6b0e041cfb7c39733/src/loadext.c#L873 , where wsdAutoext.nExt is tested against 0 outside of the SQLITE_MUTEX_STATIC_MAIN mutex that is normally used otherwise. But this does still seem OK given my understanding of multithreading and mutexes.
My hypothesis to explain what you observe would be:
If you have the possibility of building sqlite from source, one possibility would be to try to remove the optim https://github.com/sqlite/sqlite/blob/89efa897780db03eac974eb6b0e041cfb7c39733/src/loadext.c#L873 and see if that makes any difference
Or instrument sqlite3_reset_auto_extension() to see if some unexpected code would call it...
rouault commentedon Jan 13, 2024
OSGeo/gdal#9068 should likely stop the segfault, but there's still something missing to understand the full picture
ChristianBeilschmidt commentedon Feb 11, 2024
I don't know if I can add something valuable to the dscussion, but we've recently added
cargoas a dependency and our test suite ran with0.76but with0.77(geo-engine/geoengine#929) oneGdalOpenExcall withgeorust/gdalsuddenly had a SIGSEGV.Looking at this thread I noticed that
0.77got a dependency ofrusqlite, which again broughtlibsqlite3-sys=0.28. Removing this dependency seemed to remove the SIGSEGV… which is very scary.lnicola commentedon Sep 16, 2026
A nice reproducer, still needs a couple of runs to trigger.
lnicola commentedon Sep 16, 2026
So OSGeo/gdal#9068 said:
However,
OGRSQLiteBaseDataSource::FinishSpatialite()callsspatialite_cleanup_ex, which doessqlite3_reset_auto_extension, so it's actually pretty easy to trigger. That can preventOGR2SQLITE_static_registerfrom getting called until the nextOGR2SQLITE_Register.