@@ -395,7 +395,16 @@ class DuckDBFileSystemHandler final : public VSIFilesystemHandler {
395395
396396class DuckDBFileSystemPrefix final : public ClientContextState {
397397public:
398- static mutex vsi_mutex;
398+
399+ // Use an intentionally leaked heap-allocated mutex to avoid static destruction order issues.
400+ // A static mutex (either class-level or function-local) can be destroyed before the last
401+ // DuckDBFileSystemPrefix destructor runs during program teardown, causing
402+ // "mutex lock failed: Invalid argument". By heap-allocating and never freeing, we guarantee
403+ // the mutex outlives all users.
404+ static mutex &GetVSIMutex () {
405+ static mutex *mtx = new mutex ();
406+ return *mtx;
407+ }
399408
400409 explicit DuckDBFileSystemPrefix (ClientContext &context) : context(context) {
401410 // Create a new random prefix for this client
@@ -405,13 +414,17 @@ class DuckDBFileSystemPrefix final : public ClientContextState {
405414 fs_handler = make_uniq<DuckDBFileSystemHandler>(client_prefix, context);
406415
407416 // Register the file handler
408- lock_guard<mutex> lock (vsi_mutex );
417+ lock_guard<mutex> lock (GetVSIMutex () );
409418 VSIFileManager::InstallHandler (client_prefix, fs_handler.get ());
410419 }
411420
421+ // Delete copy
422+ DuckDBFileSystemPrefix (const DuckDBFileSystemPrefix &) = delete ;
423+ DuckDBFileSystemPrefix &operator =(const DuckDBFileSystemPrefix &) = delete ;
424+
412425 ~DuckDBFileSystemPrefix () override {
413426 // Uninstall the file handler for this prefix
414- lock_guard<mutex> lock (vsi_mutex );
427+ lock_guard<mutex> lock (GetVSIMutex () );
415428 VSIFileManager::RemoveHandler (client_prefix);
416429 }
417430
@@ -436,7 +449,6 @@ class DuckDBFileSystemPrefix final : public ClientContextState {
436449 unique_ptr<DuckDBFileSystemHandler> fs_handler;
437450};
438451
439- mutex DuckDBFileSystemPrefix::vsi_mutex;
440452
441453// ======================================================================================================================
442454// GDAL READ
0 commit comments