Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixed SEGV by keeping a reference to the cache object so it doesn't g…

…et GCed too early
  • Loading branch information...
commit e26cd844a808d2b4384712a7890b258a6e7fe2e3 1 parent e8766b0
@meebey authored
Showing with 47 additions and 3 deletions.
  1. +5 −0 DB.cs
  2. +7 −3 Options.cs
  3. +18 −0 tests/DBTests.cs
  4. +17 −0 tests/NativeTests.cs
View
5 DB.cs
@@ -37,6 +37,7 @@ namespace LevelDB
public class DB : IDisposable, IEnumerable<KeyValuePair<string, string>>
{
public IntPtr Handle { get; private set; }
+ Options Options { get; set; }
bool Disposed { get; set; }
public string this[string key] {
@@ -53,6 +54,9 @@ public DB(Options options, string path)
if (options == null) {
options = new Options();
}
+ // keep a reference to options as it might contain a cache object
+ // which needs to stay alive as long as the DB is not closed
+ Options = options;
Handle = Native.leveldb_open(options.Handle, path);
}
@@ -71,6 +75,7 @@ protected virtual void Dispose(bool disposing)
if (disposing) {
// free managed
+ Options = null;
}
// free unmanaged
var handle = Handle;
View
10 Options.cs
@@ -34,6 +34,8 @@ namespace LevelDB
{
public class Options
{
+ Cache f_BlockCache;
+
public IntPtr Handle { get; private set; }
// const Comparator* comparator;
@@ -72,10 +74,13 @@ public class Options
// Cache* block_cache;
public Cache BlockCache {
set {
+ // keep a reference to Cache so it doesn't get GCed
+ f_BlockCache = value;
if (value == null) {
- return;
+ Native.leveldb_options_set_cache(Handle, IntPtr.Zero);
+ } else {
+ Native.leveldb_options_set_cache(Handle, value.Handle);
}
- Native.leveldb_options_set_cache(Handle, value.Handle);
}
}
@@ -100,4 +105,3 @@ public Options()
}
}
}
-
View
18 tests/DBTests.cs
@@ -138,5 +138,23 @@ public void Enumerator()
Assert.AreEqual("key3", entries[2].Key);
Assert.AreEqual("value3", entries[2].Value);
}
+
+ [Test]
+ public void Cache()
+ {
+ Database.Dispose();
+
+ // open the DB with a cache that is not owned by LevelDB, then
+ // close DB and then free the cache
+ var options = new Options() {
+ BlockCache = new Cache(64)
+ };
+ Database = new DB(options, DatabasePath);
+ options = null;
+ GC.Collect();
+ Database.Put("key1", "value1");
+ Database.Dispose();
+ GC.Collect();
+ }
}
}
View
17 tests/NativeTests.cs
@@ -148,5 +148,22 @@ public void Enumerator()
Assert.AreEqual("key3", entries[2].Key);
Assert.AreEqual("value3", entries[2].Value);
}
+
+ [Test]
+ public void Cache()
+ {
+ Native.leveldb_close(Database);
+
+ // open the DB with a cache that is not owned by LevelDB, then
+ // close DB and then free the cache
+ var options = Native.leveldb_options_create();
+ var cache = Native.leveldb_cache_create_lru((UIntPtr) 64);
+ Native.leveldb_options_set_cache(options, cache);
+ Database = Native.leveldb_open(options, DatabasePath);
+ Native.leveldb_close(Database);
+ Database = IntPtr.Zero;
+
+ Native.leveldb_cache_destroy(cache);
+ }
}
}
Please sign in to comment.
Something went wrong with that request. Please try again.