diff --git a/libgnucash/engine/Account.cpp b/libgnucash/engine/Account.cpp index 81a5ea1f7b..0e659e8d9f 100644 --- a/libgnucash/engine/Account.cpp +++ b/libgnucash/engine/Account.cpp @@ -1347,7 +1347,7 @@ xaccFreeAccount (Account *acc) PERR (" instead of calling xaccFreeAccount(), please call\n" " xaccAccountBeginEdit(); xaccAccountDestroy();\n"); - /* First, recursively free children */ + /* First, recursively free children, also frees list */ xaccFreeAccountChildren(acc); } @@ -6114,14 +6114,32 @@ gnc_account_delete_all_bayes_maps (Account *acc) /* ================================================================ */ /* QofObject function implementation and registration */ +static void +destroy_all_child_accounts (Account *acc, gpointer data) +{ + xaccAccountBeginEdit (acc); + xaccAccountDestroy (acc); +} + static void gnc_account_book_end(QofBook* book) { - Account *root_account = gnc_book_get_root_account(book); + Account *root_account = gnc_book_get_root_account (book); + GList *accounts; + if (!root_account) return; - xaccAccountBeginEdit(root_account); - xaccAccountDestroy(root_account); + + accounts = gnc_account_get_descendants (root_account); + + if (accounts) + { + accounts = g_list_reverse (accounts); + g_list_foreach (accounts, (GFunc)destroy_all_child_accounts, nullptr); + g_list_free (accounts); + } + xaccAccountBeginEdit (root_account); + xaccAccountDestroy (root_account); } #ifdef _MSC_VER diff --git a/libgnucash/engine/SX-book.c b/libgnucash/engine/SX-book.c index 15eb1943bc..16b73ccbd7 100644 --- a/libgnucash/engine/SX-book.c +++ b/libgnucash/engine/SX-book.c @@ -180,7 +180,7 @@ static QofObject sxtg_object_def = { DI(.interface_version = ) QOF_OBJECT_VERSION, DI(.e_type = ) GNC_ID_SXTG, - DI(.type_label = ) "Scheduled Transaction Templates", + DI(.type_label = ) "Scheduled Transaction Group", DI(.create = ) NULL, DI(.book_begin = ) sxtg_book_begin, DI(.book_end = ) sxtg_book_end, @@ -281,7 +281,7 @@ book_sxes_end(QofBook* book) sxes = qof_collection_get_data(col); if (sxes != NULL) { - g_list_free (sxes->sx_list); + g_list_free(sxes->sx_list); g_object_unref(sxes); qof_collection_set_data(col, NULL); } diff --git a/libgnucash/engine/SchedXaction.c b/libgnucash/engine/SchedXaction.c index 99177e9ef5..5d0dd3d878 100644 --- a/libgnucash/engine/SchedXaction.c +++ b/libgnucash/engine/SchedXaction.c @@ -32,6 +32,7 @@ #include "Account.h" #include "SX-book.h" +#include "SX-book-p.h" #include "SX-ttinfo.h" #include "SchedXaction.h" #include "Transaction.h" @@ -497,17 +498,8 @@ xaccSchedXactionFree( SchedXaction *sx ) delete_template_trans( sx ); - /* - * xaccAccountDestroy removes the account from - * its group for us AFAICT. If shutting down, - * the account is being deleted separately. - */ - - if (!qof_book_shutting_down(qof_instance_get_book(sx))) - { - xaccAccountBeginEdit(sx->template_acct); - xaccAccountDestroy(sx->template_acct); - } + xaccAccountBeginEdit( sx->template_acct ); + xaccAccountDestroy( sx->template_acct ); for ( l = sx->deferredList; l; l = l->next ) { @@ -1220,6 +1212,9 @@ gnc_sx_book_end(QofBook* book) col = qof_book_get_collection(book, GNC_ID_SCHEDXACTION); qof_collection_foreach(col, destroy_sx_on_book_close, NULL); + + // Now destroy the template root account + gnc_book_set_template_root (book, NULL); } #ifdef _MSC_VER diff --git a/libgnucash/engine/Transaction.c b/libgnucash/engine/Transaction.c index d8255f14c0..4b1888cc36 100644 --- a/libgnucash/engine/Transaction.c +++ b/libgnucash/engine/Transaction.c @@ -1788,7 +1788,7 @@ xaccTransRollbackEdit (Transaction *trans) xaccSplitRollbackEdit(s); SWAP_STR(s->action, so->action); SWAP_STR(s->memo, so->memo); - qof_instance_copy_kvp (QOF_INSTANCE (s), QOF_INSTANCE (so)); + qof_instance_copy_kvp (QOF_INSTANCE (s), QOF_INSTANCE (so)); s->reconciled = so->reconciled; s->amount = so->amount; s->value = so->value; @@ -1797,7 +1797,6 @@ xaccTransRollbackEdit (Transaction *trans) //SET_GAINS_A_VDIRTY(s); s->date_reconciled = so->date_reconciled; qof_instance_mark_clean(QOF_INSTANCE(s)); - xaccFreeSplit(so); } else { @@ -1824,6 +1823,10 @@ xaccTransRollbackEdit (Transaction *trans) } } g_list_free(slist); + + // orig->splits may still have duped splits so free them + for (node = orig->splits; node; node = node->next) + xaccFreeSplit(node->data); g_list_free(orig->splits); orig->splits = NULL; diff --git a/libgnucash/engine/gnc-pricedb.c b/libgnucash/engine/gnc-pricedb.c index 777e9f8a42..3b2a55e7cb 100644 --- a/libgnucash/engine/gnc-pricedb.c +++ b/libgnucash/engine/gnc-pricedb.c @@ -2493,6 +2493,9 @@ convert_price (const gnc_commodity *from, const gnc_commodity *to, PriceTuple tu price = gnc_numeric_div (to_val, from_val, GNC_DENOM_AUTO, no_round); + gnc_price_unref (tuple.from); + gnc_price_unref (tuple.to); + if (from_cur == from && to_cur == to) return price; diff --git a/libgnucash/engine/gncBillTerm.c b/libgnucash/engine/gncBillTerm.c index 3338b1433f..6d15c55fd5 100644 --- a/libgnucash/engine/gncBillTerm.c +++ b/libgnucash/engine/gncBillTerm.c @@ -839,14 +839,28 @@ static void _gncBillTermCreate (QofBook *book) qof_book_set_data (book, _GNC_MOD_NAME, bi); } + +static void +destroy_billterm_on_book_close (QofInstance *ent, gpointer data) +{ + GncBillTerm *term = GNC_BILLTERM(ent); + + gncBillTermBeginEdit (term); + gncBillTermDestroy (term); +} + static void _gncBillTermDestroy (QofBook *book) { struct _book_info *bi; + QofCollection *col; if (!book) return; bi = qof_book_get_data (book, _GNC_MOD_NAME); + col = qof_book_get_collection (book, GNC_ID_BILLTERM); + qof_collection_foreach (col, destroy_billterm_on_book_close, NULL); + g_list_free (bi->terms); g_free (bi); } diff --git a/libgnucash/engine/gncCustomer.c b/libgnucash/engine/gncCustomer.c index ddb03aee04..676a7ed4cc 100644 --- a/libgnucash/engine/gncCustomer.c +++ b/libgnucash/engine/gncCustomer.c @@ -353,14 +353,17 @@ static void gncCustomerFree (GncCustomer *cust) gncAddressDestroy (cust->addr); gncAddressBeginEdit (cust->shipaddr); gncAddressDestroy (cust->shipaddr); + + gncJobFreeList (cust->jobs); g_list_free (cust->jobs); g_free (cust->balance); - if (cust->terms) - gncBillTermDecRef (cust->terms); - if (cust->taxtable) + if (!qof_book_shutting_down (qof_instance_get_book (QOF_INSTANCE(cust)))) { - gncTaxTableDecRef (cust->taxtable); + if (cust->terms) + gncBillTermDecRef (cust->terms); + if (cust->taxtable) + gncTaxTableDecRef (cust->taxtable); } /* qof_instance_release (&cust->inst); */ diff --git a/libgnucash/engine/gncEntry.c b/libgnucash/engine/gncEntry.c index 449abcabfb..c5c6ccd779 100644 --- a/libgnucash/engine/gncEntry.c +++ b/libgnucash/engine/gncEntry.c @@ -463,10 +463,14 @@ static void gncEntryFree (GncEntry *entry) gncAccountValueDestroy (entry->i_tax_values); if (entry->b_tax_values) gncAccountValueDestroy (entry->b_tax_values); - if (entry->i_tax_table) - gncTaxTableDecRef (entry->i_tax_table); - if (entry->b_tax_table) - gncTaxTableDecRef (entry->b_tax_table); + + if (!qof_book_shutting_down (qof_instance_get_book (QOF_INSTANCE(entry)))) + { + if (entry->i_tax_table) + gncTaxTableDecRef (entry->i_tax_table); + if (entry->b_tax_table) + gncTaxTableDecRef (entry->b_tax_table); + } /* qof_instance_release (&entry->inst); */ g_object_unref (entry); diff --git a/libgnucash/engine/gncInvoice.c b/libgnucash/engine/gncInvoice.c index 7f8f923c3e..eedad7c70b 100644 --- a/libgnucash/engine/gncInvoice.c +++ b/libgnucash/engine/gncInvoice.c @@ -435,10 +435,14 @@ static void gncInvoiceFree (GncInvoice *invoice) g_list_free (invoice->entries); g_list_free (invoice->prices); - if (invoice->printname) g_free (invoice->printname); + if (invoice->printname) + g_free (invoice->printname); - if (invoice->terms) - gncBillTermDecRef (invoice->terms); + if (!qof_book_shutting_down (qof_instance_get_book (QOF_INSTANCE(invoice)))) + { + if (invoice->terms) + gncBillTermDecRef (invoice->terms); + } if (invoice->doclink != is_unset) g_free (invoice->doclink); diff --git a/libgnucash/engine/gncJob.c b/libgnucash/engine/gncJob.c index 46fb843d61..8d9e42297d 100644 --- a/libgnucash/engine/gncJob.c +++ b/libgnucash/engine/gncJob.c @@ -231,6 +231,18 @@ GncJob *gncJobCreate (QofBook *book) return job; } +static void free_job_list (GncJob *job) +{ + gncJobBeginEdit (job); + gncJobDestroy (job); +} + +void gncJobFreeList (GList *jobs) +{ + GList *job_list = g_list_copy (jobs); + g_list_free_full (job_list, (GDestroyNotify)free_job_list); +} + void gncJobDestroy (GncJob *job) { if (!job) return; diff --git a/libgnucash/engine/gncJob.h b/libgnucash/engine/gncJob.h index b40cdbcab4..e68585f9e3 100644 --- a/libgnucash/engine/gncJob.h +++ b/libgnucash/engine/gncJob.h @@ -57,6 +57,7 @@ GType gnc_job_get_type(void); GncJob *gncJobCreate (QofBook *book); void gncJobDestroy (GncJob *job); +void gncJobFreeList (GList *jobs); /** \name Set Functions @{ diff --git a/libgnucash/engine/gncTaxTable.c b/libgnucash/engine/gncTaxTable.c index 2e0cbfa907..04d4a4ff30 100644 --- a/libgnucash/engine/gncTaxTable.c +++ b/libgnucash/engine/gncTaxTable.c @@ -1015,14 +1015,27 @@ static void _gncTaxTableCreate (QofBook *book) qof_book_set_data (book, _GNC_MOD_NAME, bi); } +static void +destroy_taxtable_on_book_close (QofInstance *ent, gpointer data) +{ + GncTaxTable *table = GNC_TAXTABLE(ent); + + gncTaxTableBeginEdit (table); + gncTaxTableDestroy (table); +} + static void _gncTaxTableDestroy (QofBook *book) { struct _book_info *bi; + QofCollection *col; if (!book) return; bi = qof_book_get_data (book, _GNC_MOD_NAME); + col = qof_book_get_collection (book, GNC_ID_TAXTABLE); + qof_collection_foreach (col, destroy_taxtable_on_book_close, NULL); + g_list_free (bi->tables); g_free (bi); } diff --git a/libgnucash/engine/gncVendor.c b/libgnucash/engine/gncVendor.c index 67af18c61e..1fa0a34100 100644 --- a/libgnucash/engine/gncVendor.c +++ b/libgnucash/engine/gncVendor.c @@ -496,13 +496,18 @@ static void gncVendorFree (GncVendor *vendor) CACHE_REMOVE (vendor->notes); gncAddressBeginEdit (vendor->addr); gncAddressDestroy (vendor->addr); + + gncJobFreeList (vendor->jobs); g_list_free (vendor->jobs); g_free (vendor->balance); - if (vendor->terms) - gncBillTermDecRef (vendor->terms); - if (vendor->taxtable) - gncTaxTableDecRef (vendor->taxtable); + if (!qof_book_shutting_down (qof_instance_get_book (QOF_INSTANCE(vendor)))) + { + if (vendor->terms) + gncBillTermDecRef (vendor->terms); + if (vendor->taxtable) + gncTaxTableDecRef (vendor->taxtable); + } /* qof_instance_release (&vendor->inst); */ g_object_unref (vendor);