1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
|
# frozen_string_literal: true
require "weakref"
module SQLite3
# based on Rails's active_support/fork_tracker.rb
module ForkSafety
module CoreExt # :nodoc:
def _fork
pid = super
if pid == 0
ForkSafety.discard
end
pid
end
end
@databases = []
@mutex = Mutex.new
@suppress = false
class << self
def hook! # :nodoc:
::Process.singleton_class.prepend(CoreExt)
end
def track(database) # :nodoc:
@mutex.synchronize do
@databases << WeakRef.new(database)
end
end
def discard # :nodoc:
warned = @suppress
@databases.each do |db|
next unless db.weakref_alive?
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
rescue WeakRef::RefError
# GC may run while this method is executing, and that's OK
end
end
@databases.clear
end
# Call to suppress the fork-related warnings.
def suppress_warnings!
@suppress = true
end
end
end
end
SQLite3::ForkSafety.hook!
|