# # patch "ChangeLog" # from [f6446003e4e0c79f9e01a66ece2624dceaf02919] # to [10f5571096a56bc32f62bc5e29a88e9181fc68d0] # # patch "database.cc" # from [cbc204bdeb3fdf897c97b0771f3b48c8a4d85d0e] # to [7e793889cee7cbbd201744d7d299e4aac84d42f4] # ======================================================================== --- ChangeLog f6446003e4e0c79f9e01a66ece2624dceaf02919 +++ ChangeLog 10f5571096a56bc32f62bc5e29a88e9181fc68d0 @@ -1,5 +1,11 @@ 2005-10-08 Nathaniel Smith + * database.cc (fetch): Do not insert prepared statements into the + statement table until they are successfully created, to avoid + segfaults on database teardown. + +2005-10-08 Nathaniel Smith + * contrib/ciabot_monotone.py (send_change_for): Handle branch-less revisions. ======================================================================== --- database.cc cbc204bdeb3fdf897c97b0771f3b48c8a4d85d0e +++ database.cc 7e793889cee7cbbd201744d7d299e4aac84d42f4 @@ -582,12 +582,16 @@ map::iterator i = statement_cache.find(query); if (i == statement_cache.end()) { - statement_cache.insert(make_pair(query, statement())); - i = statement_cache.find(query); - I(i != statement_cache.end()); - + statement s; const char * tail; - sqlite3_prepare(sql(), query, -1, &i->second.stmt, &tail); + // this line can throw, which leaves our statement uninitialized. so we + // insert the statement into the table _after_ running it successfully. + sqlite3_prepare(sql(), query, -1, &s.stmt, &tail); + // note that this copies the statement, and thus the statement pointer. + // But we immediately tear down s, so we still end up with a single + // unique pointer to the statement, on which sqlite3_finalize will + // eventually be called by ~database. + statement_cache.insert(make_pair(query, s)); assert_sqlite3_ok(sql()); L(F("prepared statement %s\n") % query);