GNOME Bugzilla – Bug 632362
Unable to create "reversing transaction" again after it is removed (using SQLite, MySQL, Postgres data storage, but not XML storage)
Last modified: 2018-06-29 22:45:59 UTC
This error occures only if SQLite, MySQL or Postgres data storage is used. If XML storage is used - there is no this kind of error. After reversing transaction is created and deleted by any reason, you can't create another one reversing transaction until reload the SQLite file or GnuCash is closed and reopened. You will see a mesage: "reversing transaction is already exist", but it was deleted a few seconds ago. Steps to reproduce: 1. Create any transaction. 2. Add a reversing transaction to the first one. (Reversing transaction is created.) 3. Detete this created reversing transaction. (Reversing transaction is succesfully deleted. 5. Try to create reversing transaction one more time. (See the message "reversing transaction is already exist")
The root cause is a ref-counting error in the sql backend: For some reason the reversing transaction gets a rather large reference count (5 in one try, 7 in another), so the g_object_unref() at the end of xaccFreeTransaction doesn't release the object. The details: A reversing transaction creates a kvp entry on the reversed transaction containing the GUID. xaccTransGetReversedBy looks up the GUID in the book's master entity collection and returns the pointer if it's found and NULL otherwise. If gnc_plugin_page_register_command_reverse_transaction() gets a pointer, it puts up the "already got one" messagebox and quits. That master entry is created during construction of the QofInstance and removed at disposal. Since the SQL backend-based reversing transaction has accumulated extra ref counts, dispose never runs and the GUID is never removed from the collection, so the second reverse fails. Another issue: If you quit Gnucash, or switch to another file and back, the deleted transaction is cleared from the entities collection and you can create a reversing transaction -- even if you *don't* delete the first reversing transaction. But if you do delete the first reversing transaction and then save as XML, you *can't* create a new reversing transaction there. One more thing: There are *no* calls to g_object_ref() in the engine or the backend, so how the heck is that transaction's ref count getting boosted?
It turns out that g_value_set_object() calls g_object_ref(), and so does g_object_get() (by way of g_object_duplicate()), but g_object_get() only calls g_object_unref() once at the other end, so it leaks. Replacing g_value_set_object() with g_object_take_object() in all of the foo_get_property() instances eliminates the leak and it works correctly. r23192/4
GnuCash bug tracking has moved to a new Bugzilla host. This bug has been copied to https://bugs.gnucash.org/show_bug.cgi?id=632362. Please update any external references or bookmarks.