Skip to content

Commit 3ba5cd0

Browse files
haileysflavorjones
andcommitted
always call sqlite3_finalize in deallocate func
prevents memory leak when `close` is not called before a ResultSet is garbage collected also add coverage for statement resource cleanup Co-authored-by: Mike Dalessio <[email protected]>
1 parent 345e5db commit 3ba5cd0

File tree

3 files changed

+40
-1
lines changed

3 files changed

+40
-1
lines changed

ext/sqlite3/statement.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,17 @@
66

77
VALUE cSqlite3Statement;
88

9+
static void statement_deallocate(void *data)
10+
{
11+
sqlite3StmtRubyPtr s = (sqlite3StmtRubyPtr)data;
12+
13+
if (s->st) {
14+
sqlite3_finalize(s->st);
15+
}
16+
17+
xfree(data);
18+
}
19+
920
static size_t statement_memsize(const void *data)
1021
{
1122
const sqlite3StmtRubyPtr s = (const sqlite3StmtRubyPtr)data;
@@ -17,7 +28,7 @@ static const rb_data_type_t statement_type = {
1728
"SQLite3::Backup",
1829
{
1930
NULL,
20-
RUBY_TYPED_DEFAULT_FREE,
31+
statement_deallocate,
2132
statement_memsize,
2233
},
2334
0,

sqlite3.gemspec

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ Gem::Specification.new do |s|
8989
"test/test_integration_resultset.rb",
9090
"test/test_integration_statement.rb",
9191
"test/test_pragmas.rb",
92+
"test/test_resource_cleanup.rb",
9293
"test/test_result_set.rb",
9394
"test/test_sqlite3.rb",
9495
"test/test_statement.rb",

test/test_resource_cleanup.rb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
require "helper"
2+
3+
module SQLite3
4+
# these tests will cause ruby_memcheck to report a leak if we're not cleaning up resources
5+
class TestResourceCleanup < SQLite3::TestCase
6+
def test_cleanup_unclosed_database_object
7+
100.times do
8+
SQLite3::Database.new(':memory:')
9+
end
10+
end
11+
12+
def test_cleanup_unclosed_statement_object
13+
100.times do
14+
db = SQLite3::Database.new(':memory:')
15+
db.execute('create table foo(text BLOB)')
16+
db.prepare('select * from foo')
17+
end
18+
end
19+
20+
# def test_cleanup_unclosed_resultset_object
21+
# db = SQLite3::Database.new(':memory:')
22+
# db.execute('create table foo(text BLOB)')
23+
# stmt = db.prepare('select * from foo')
24+
# stmt.execute
25+
# end
26+
end
27+
end

0 commit comments

Comments
 (0)