Revision aa53579d6cc5a53c1493bbda4f21c0e9831b377b authored by Yanqin Jin on 25 May 2018, 18:45:12 UTC, committed by Facebook Github Bot on 25 May 2018, 18:57:51 UTC
Summary:
Please refer to earlier discussion in [issue 3609](https://github.com/facebook/rocksdb/issues/3609).
There was also an alternative fix in [PR 3888](https://github.com/facebook/rocksdb/pull/3888), but the proposed solution requires complex change.

To summarize the cause of the problem. Upon creation of a column family, a `BlockBasedTableFactory` object is `new`ed and encapsulated by a `std::shared_ptr`. Since there is no other `std::shared_ptr` pointing to this `BlockBasedTableFactory`, when the column family is dropped, the `ColumnFamilyData` is `delete`d, causing the destructor of `std::shared_ptr`. Since there is no other `std::shared_ptr`, the underlying memory is also freed.
Later when the db exits, it releases all the table readers, including the table readers that have been operating on the dropped column family. This needs to access the `table_options` owned by `BlockBasedTableFactory` that has already been deleted. Therefore, a segfault is raised.
Previous workaround is to purge all obsolete files upon `ColumnFamilyData` destruction, which leads to a force release of table readers of the dropped column family. However this does not work when the user disables file deletion.

Our solution in this PR is making a copy of `table_options` in `BlockBasedTable::Rep`. This solution increases memory copy and usage, but is much simpler.

Test plan
```
$ make -j16
$ ./column_family_test --gtest_filter=ColumnFamilyTest.CreateDropAndDestroy:ColumnFamilyTest.CreateDropAndDestroyWithoutFileDeletion
```

Expected behavior:
All tests should pass.
Closes https://github.com/facebook/rocksdb/pull/3898

Differential Revision: D8149421

Pulled By: riversand963

fbshipit-source-id: eaecc2e064057ef607fbdd4cc275874f866c3438
1 parent 6e08916
Raw File
Vagrantfile
# Vagrant file
Vagrant.configure("2") do |config|

  config.vm.provider "virtualbox" do |v|
    v.memory = 4096
    v.cpus = 2
  end

  config.vm.define "ubuntu14" do |box|
    box.vm.box = "ubuntu/trusty64"
  end

  config.vm.define "centos65" do |box|
    box.vm.box = "chef/centos-6.5"
  end

  config.vm.define "centos7" do |box|
    box.vm.box = "centos/7"
    box.vm.provision "shell", path: "build_tools/setup_centos7.sh"
  end

  config.vm.define "FreeBSD10" do |box|
    box.vm.guest = :freebsd
    box.vm.box = "robin/freebsd-10"
    # FreeBSD does not support 'mount_virtualbox_shared_folder', use NFS
    box.vm.synced_folder ".", "/vagrant", :nfs => true, id: "vagrant-root"
    box.vm.network "private_network", ip: "10.0.1.10"

    # build everything after creating VM, skip using --no-provision
    box.vm.provision "shell", inline: <<-SCRIPT
      pkg install -y gmake clang35
      export CXX=/usr/local/bin/clang++35
      cd /vagrant
      gmake clean
      gmake all OPT=-g
    SCRIPT
  end

end
back to top