> 28.03.2014 17:43, Dimitry Sibiryakov wrote: >> Either I don't understand something or garbage_collect_idx() doesn't do >> what it is >> supposed to do. > > I've found the problem. Global variables must die. Only miracle prevents > this piece of > code from crash: > > > undo = action->vct_undo->current().setupRecord(transaction); > > Because this call uses (relatively) global record buffer, content of > 'old_data' is > replaced with 'undo', so the data that should go is wrong.
You are close to the reason of the issue but overestimate "globality" of record buffer and not see a correct point where the problem starts. 1. "globality" Record buffer is cached at the transaction level and exists in single instance. It is OK while we use just one instance of record buffer at the same time. Record buffer used in two routines: verb_post() and VIO_verb_cleanup(). a) verb_post() can't use more than one instance of record buffer itself and have no recursive calls nor VIO_verb_cleanup() calls b) VIO_verb_cleanup() also can't use more than one instance of record buffer itself but it could call verb_post() while record buffer is already used: Record* const record = action->vct_undo->current().setupRecord(transaction); const bool same_tx = (record->rec_flags & REC_same_tx) != 0; const bool new_ver = (record->rec_flags & REC_new_version) != 0; if (record->rec_length != 0) { record_param new_rpb = rpb; new_rpb.rpb_record = record; new_rpb.rpb_address = record->rec_data; new_rpb.rpb_length = record->rec_length; verb_post(tdbb, transaction, &rpb, record, /*&new_rpb,*/ same_tx, new_ver); } 2. Correct place to fix: as you see above, we should fix VIO_verb_cleanup() (not verb_post() as you points). Or we can change jrd_tra to allow it to cache more than one record buffer. Here i want to know opinions of others. Don't panic, Vlad :) ------------------------------------------------------------------------------ Firebird-Devel mailing list, web interface at https://lists.sourceforge.net/lists/listinfo/firebird-devel