View Issue Details
|ID||Project||Category||View Status||Date Submitted||Last Update|
|0037981||Lazarus||Database Components||public||2020-10-25 02:15||2020-10-27 02:13|
|Reporter||Pedro Gimeno||Assigned To|
|Product Version||2.1 (SVN)|
|Summary||0037981: Crash when opening a TCustomBufDataSet descendant with FieldDef's|
|Description||When a dataset is being opened, TCustomBufDataSet's InternalOpen calls IntLoadFieldDefsFromFile, which in turn calls FieldDefs.Clear. This frees all the FieldDef's that it contained, but apparently Lazarus has them cached and doesn't have any means to synchronize its cache with the component's FieldDefs list.|
As a result of Lazarus using the cached, now freed object, random crashes happen. The backtrace is not very telling, because the problem had already happened earlier when freeing the objects, but it's the one already posted in 0037870. Here's the most relevant excerpt:
#0 INHERITSFROM (self=0x7fffe978f4b8, ACLASS=0x213ba10) at ../inc/objpas.inc:625 0000001 0x000000000213ba55 in VMT_$CLASSES_$$_TCOMPONENT () 0000002 0x0000000000435b43 in fpc_do_is (ACLASS=0x12438081, AOBJECT=0x213ba10) at ../inc/objpas.inc:42 0000003 0x00007fffeca8f755 in ?? () 0000004 0x0000000001030d53 in UPDATECOMPONENTNODE (parentfp=0x7fffffffc240, ANODE=0x7fffeca8f7a0) at componenttreeview.pas:750 0000005 0x0000000001030dcb in UPDATECOMPONENTNODE (parentfp=0x7fffffffc240, ANODE=0x7fffeca8f700) at componenttreeview.pas:756 0000006 0x0000000001030dcb in UPDATECOMPONENTNODE (parentfp=0x7fffffffc240, ANODE=0x7fffeca8f660) at componenttreeview.pas:756 0000007 0x0000000001030de0 in UPDATECOMPONENTNODE (parentfp=0x7fffffffc240, ANODE=0x7fffeca8f5c0) at componenttreeview.pas:757 0000008 0x0000000001030de0 in UPDATECOMPONENTNODE (parentfp=0x7fffffffc240, ANODE=0x7fffeca8f520) at componenttreeview.pas:757 0000009 0x0000000001030dcb in UPDATECOMPONENTNODE (parentfp=0x7fffffffc240, ANODE=0x7fffeca8f480) at componenttreeview.pas:756 0000010 0x0000000001030ccd in UPDATECOMPONENTNODESVALUES (this=0x7fffed14c010) at componenttreeview.pas:762
I'm on the fence about whether this is a problem in Lazarus, or in the FPC database libraries. It's arguably unexpected for a dataset to remove field definitions that the user may have altered, after the form has loaded. However, this lack of persistence (verified) may be considered a separate bug; in that case, the problem would arguably be that Lazarus is not subscribing to FieldDefs notifications in order to keep its cache up to date.
A similar problem might exist with IndexDefs. I haven't checked if it's currently a problem, but if the datasets are allowed to add or remove IndexDefs at any time, to prevent future problems it would be best to do something to sync the IndexDefs with Lazarus' cache.
|Steps To Reproduce||1. Create a file somewhere with a single line containing a number, e.g. echo 1 > /tmp/test.csv|
2. Add a TCSVDataSet to a form or datamodule.
3. Set the filename property to the file created in step 1.
4. Open and close the TCSVDataSet. This creates a FieldDef in the FieldDefs list. Alternatively, create one manually.
5. Ensure you leave the TCSVDataSet, and click it again. This refresh FieldDefs which now shows 1 item.
6. Open the dataset again. If you don't get any crash (possibly in the mild form of an Access Violation window), more iterations of closing/reopening will probably do it. Sometimes it crashes during closing.
If this recipe doesn't work, try saving the form with the FieldDef in it and the dataset closed, then restart the IDE and try opening and closing the dataset several times.
|Tags||No tags attached.|
|Fixed in Revision|
This is most likely also an FPC issue because TCSVDataSet inherits from TBufDataset.
Please test if you can reproduce with TBufDataset.
After more debugging, I'm now 100% sure that it is a Lazarus issue, in particular with the ComponentTreeView (the one above the properties list). I think it should add an observer for the published properties of the TCollection type, that causes the tree to be rebuilt.
The crashes I'm getting are all related to the tree view, see backtrace. The cached FieldDef's(*) I was talking about are part of the ComponentTreeView.
For the reproduction recipe mentioned above, what's happening is that FieldDefs is being cleared, then rebuilt, but the ComponentTreeView is not updated accordingly, and still holds a cached reference to the (now deleted) old FieldDef's. As soon as something causes an update of the values of the ComponentTreeView without forcing the tree to rebuild, the crash happens.
Here's another way to reproduce the issue with a TBufDataset:
1. Create a TBufDataset.
2. Add some FieldDef's. Set the field type to something, e.g. ftInteger.
3. Right click on it and select 'Create dataset'.
4. Click outside and then click on the dataset again. You should see that there are 2 IndexDef's.
5. Get the tree view's tree to be rebuilt somehow. I triggered that by deleting a FieldDef. That causes the two indexes to appear in the tree.
6. Close the dataset. That causes the two indexes to be deleted. That's standard operation procedure for TBufDataset, you can't really blame it for doing that.
However, now the freed IndexDef's are also being accessed by the tree view, as a result of UpdateComponentNode (I presume that updates values only, without a tree rebuild). That's what causes the crash.
(*) Note: I've tried to separate FIeldDefs, which is a list, from FieldDef, which is an element of the list. I've used FieldDef's to indicate the plural of each element, and FieldDefs to refer to the list itself. That also applies to the OP.