From ec11e4c88ea6a0290d2b23a968eb176a59aa7ec4 Mon Sep 17 00:00:00 2001 From: Mike Dalessio Date: Wed, 4 Dec 2024 16:37:02 -0500 Subject: [PATCH] fix: handle the case where GC runs during fork safety checks If GC runs between the check for `db.weakref_alive?` and `db.close` then an exception will be raised: Invalid Reference - probably recycled (WeakRef::RefError) In this case, let's just swallow the error and keep going, since the database object isn't in use and was GCed. --- lib/sqlite3/fork_safety.rb | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/lib/sqlite3/fork_safety.rb b/lib/sqlite3/fork_safety.rb index 79eb8b52..a1bc175a 100644 --- a/lib/sqlite3/fork_safety.rb +++ b/lib/sqlite3/fork_safety.rb @@ -35,17 +35,21 @@ def discard # :nodoc: @databases.each do |db| next unless db.weakref_alive? - unless db.closed? || db.readonly? - unless warned - # If you are here, you may want to read - # https://github.com/sparklemotion/sqlite3-ruby/pull/558 - warn("Writable sqlite database connection(s) were inherited from a forked process. " \ - "This is unsafe and the connections are being closed to prevent possible data " \ - "corruption. Please close writable sqlite database connections before forking.", - uplevel: 0) - warned = true + begin + unless db.closed? || db.readonly? + unless warned + # If you are here, you may want to read + # https://github.com/sparklemotion/sqlite3-ruby/pull/558 + warn("Writable sqlite database connection(s) were inherited from a forked process. " \ + "This is unsafe and the connections are being closed to prevent possible data " \ + "corruption. Please close writable sqlite database connections before forking.", + uplevel: 0) + warned = true + end + db.close end - db.close + rescue WeakRef::RefError + # GC may run while this method is executing, and that's OK end end @databases.clear