diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9ac6e3ac..9516ee0a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: fail-fast: false matrix: os: [ubuntu, macos, windows] - ruby: ["3.3", "3.2", "3.1", "3.0"] + ruby: ["3.3", "3.2", "3.1"] syslib: [enable, disable] include: # additional compilation flags for homebrew @@ -122,7 +122,7 @@ jobs: fail-fast: false matrix: os: [ubuntu, macos, windows] - ruby: ["3.3", "3.0"] # oldest and newest + ruby: ["3.3", "3.1"] # oldest and newest include: - { os: windows, ruby: mingw } - { os: windows, ruby: mswin } @@ -213,7 +213,7 @@ jobs: fail-fast: false matrix: os: [ubuntu, macos, windows] - ruby: ["3.3", "3.2", "3.1", "3.0"] + ruby: ["3.3", "3.2", "3.1"] syslib: [enable, disable] include: # additional compilation flags for homebrew @@ -284,7 +284,7 @@ jobs: - x86-linux-musl - x86_64-linux-gnu - x86_64-linux-musl - ruby: ["3.3", "3.2", "3.1", "3.0"] + ruby: ["3.3", "3.2", "3.1"] include: # declare docker image for each platform - { platform: aarch64-linux-musl, docker_tag: "-alpine", bootstrap: "apk add build-base &&" } @@ -322,15 +322,12 @@ jobs: fail-fast: false matrix: os: [windows-latest, macos-13, macos-14] - ruby: ["3.3", "3.2", "3.1", "3.0"] + ruby: ["3.3", "3.2", "3.1"] include: - os: macos-13 platform: x86_64-darwin - os: macos-14 platform: arm64-darwin - - os: windows-latest - ruby: "3.0" - platform: x64-mingw32 - os: windows-latest ruby: "3.1" platform: x64-mingw-ucrt @@ -359,7 +356,6 @@ jobs: fail-fast: false matrix: include: - - { ruby: "3.0", flavor: "alpine" } - { ruby: "3.1", flavor: "alpine3.18" } - { ruby: "3.1", flavor: "alpine3.19" } - { ruby: "3.2", flavor: "alpine3.18" } @@ -376,6 +372,4 @@ jobs: name: cruby-x86_64-linux-musl-gem path: gems - run: apk add build-base - - if: matrix.ruby == '3.0' # https://github.com/rake-compiler/rake-compiler/pull/236 - run: gem update --system - run: ./bin/test-gem-install ./gems diff --git a/.rubocop.yml b/.rubocop.yml index faeea9f9..62458687 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -13,7 +13,7 @@ inherit_gem: AllCops: SuggestExtensions: false - TargetRubyVersion: 3.0 + TargetRubyVersion: 3.1 Naming/InclusiveLanguage: Enabled: true diff --git a/CHANGELOG.md b/CHANGELOG.md index a7047ed4..00a58846 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,21 @@ ## next / unreleased -### Changed +### Ruby + +- This release drops support for Ruby 3.0. + + +### Fork safety improvements + +Sqlite itself is [not fork-safe](https://www.sqlite.org/howtocorrupt.html#_carrying_an_open_database_connection_across_a_fork_). Specifically, writing in a child process to a database connection that was created in the parent process may corrupt the database file. To mitigate this risk, sqlite3-ruby has implemented the following changes: + +- Open writable database connections carried across a `fork()` will immediately be closed in the child process to mitigate the risk of corrupting the database file. +- These connections will be incompletely closed ("discarded") which will result in a one-time memory leak in the child process. + +If it's at all possible, we strongly recommend that you close writable database connections in the parent before forking. -- Any database connections carried across a `fork()` will not be fully closed to help protect database files against corruption. Using a database connection in a child process that was created in a parent process is unsafe and may corrupt the database file. If an inherited connection is closed then a warning will be emitted and some reserved memory will be lost to the child process permanently. See the README "Fork Safety" section and `adr/2024-09-fork-safety.md` for more information. [#558] @flavorjones +See the README "Fork Safety" section and `adr/2024-09-fork-safety.md` for more information. [#558] @flavorjones ### Improved diff --git a/INSTALLATION.md b/INSTALLATION.md index 50e5055c..29ec597a 100644 --- a/INSTALLATION.md +++ b/INSTALLATION.md @@ -21,8 +21,6 @@ In v2.0.0 and later, native (precompiled) gems are available for recent Ruby ver - `x86_64-linux-gnu` (requires: glibc >= 2.17) - `x86_64-linux-musl` -⚠ Ruby 3.0 linux users must use Rubygems >= 3.3.22 in order to use these gems. - ⚠ Musl linux users should update to Bundler >= 2.5.6 to avoid https://github.com/rubygems/rubygems/issues/7432 If you are using one of these Ruby versions on one of these platforms, the native gem is the recommended way to install sqlite3-ruby. diff --git a/bin/test-gem-file-contents b/bin/test-gem-file-contents index 284c4fea..8ae6bea7 100755 --- a/bin/test-gem-file-contents +++ b/bin/test-gem-file-contents @@ -65,22 +65,7 @@ Minitest::Reporters.use!([Minitest::Reporters::SpecReporter.new]) puts "Testing '#{gemfile}' (#{gemspec.platform})" describe File.basename(gemfile) do - let(:all_supported_ruby_versions) { - ["3.0", "3.1", "3.2", "3.3"] - } - let(:native_supported_ruby_versions) { ["3.0", "3.1", "3.2", "3.3"] } - let(:ucrt_supported_ruby_versions) { ["3.1", "3.2", "3.3"] } - let(:platform_supported_ruby_versions) do - if gemspec.platform.to_s == "x64-mingw-ucrt" - ucrt_supported_ruby_versions - elsif gemspec.platform.to_s == "x64-mingw32" - native_supported_ruby_versions - ucrt_supported_ruby_versions - elsif gemspec.platform.cpu - native_supported_ruby_versions - else - all_supported_ruby_versions - end - end + let(:supported_ruby_versions) { ["3.1", "3.2", "3.3"] } describe "setup" do it "gemfile contains some files" do @@ -147,7 +132,7 @@ describe File.basename(gemfile) do end it "sets required_ruby_version appropriately" do - all_supported_ruby_versions.each do |v| + supported_ruby_versions.each do |v| assert( gemspec.required_ruby_version.satisfied_by?(Gem::Version.new(v)), "required_ruby_version='#{gemspec.required_ruby_version}' should support ruby #{v}" @@ -181,7 +166,7 @@ describe File.basename(gemfile) do end it "contains expected shared library files " do - platform_supported_ruby_versions.each do |version| + supported_ruby_versions.each do |version| actual = gemfile_contents.find do |p| File.fnmatch?("lib/sqlite3/#{version}/sqlite3_native.{so,bundle}", p, File::FNM_EXTGLOB) end @@ -197,26 +182,19 @@ describe File.basename(gemfile) do File.fnmatch?("lib/sqlite3/**/*.{so,bundle}", p, File::FNM_EXTGLOB) end assert_equal( - platform_supported_ruby_versions.length, + supported_ruby_versions.length, actual.length, "did not expect extra shared library files" ) end it "sets required_ruby_version appropriately" do - unsupported_versions = all_supported_ruby_versions - platform_supported_ruby_versions - platform_supported_ruby_versions.each do |v| + supported_ruby_versions.each do |v| assert( gemspec.required_ruby_version.satisfied_by?(Gem::Version.new(v)), "required_ruby_version='#{gemspec.required_ruby_version}' should support ruby #{v}" ) end - unsupported_versions.each do |v| - refute( - gemspec.required_ruby_version.satisfied_by?(Gem::Version.new(v)), - "required_ruby_version='#{gemspec.required_ruby_version}' should not support ruby #{v}" - ) - end end it "does not set metadata for msys2" do diff --git a/rakelib/native.rake b/rakelib/native.rake index ff9177a8..d146ac3c 100644 --- a/rakelib/native.rake +++ b/rakelib/native.rake @@ -6,7 +6,7 @@ require "rake/extensiontask" require "rake_compiler_dock" require "yaml" -cross_rubies = ["3.3.0", "3.2.0", "3.1.0", "3.0.0"] +cross_rubies = ["3.3.0", "3.2.0", "3.1.0"] cross_platforms = [ "aarch64-linux-gnu", "aarch64-linux-musl", diff --git a/sqlite3.gemspec b/sqlite3.gemspec index 4174ba12..8283fbed 100644 --- a/sqlite3.gemspec +++ b/sqlite3.gemspec @@ -18,7 +18,7 @@ Gem::Specification.new do |s| s.licenses = ["BSD-3-Clause"] - s.required_ruby_version = Gem::Requirement.new(">= 3.0") + s.required_ruby_version = Gem::Requirement.new(">= 3.1") s.homepage = "https://github.com/sparklemotion/sqlite3-ruby" s.metadata = { diff --git a/test/test_database.rb b/test/test_database.rb index 0dbb0b37..e866a811 100644 --- a/test/test_database.rb +++ b/test/test_database.rb @@ -727,7 +727,6 @@ class TestDiscardDatabase < SQLite3::TestCase def test_fork_discards_an_open_readwrite_connection skip("interpreter doesn't support fork") unless Process.respond_to?(:fork) skip("valgrind doesn't handle forking") if i_am_running_in_valgrind - skip("ruby 3.0 doesn't have Process._fork") if RUBY_VERSION < "3.1.0" GC.start begin