ExBemined Posted May 4, 2020 Posted May 4, 2020 We are trying to migrate some code from Unigine 2.9 to 2.11. This project unfortunately included a bunch of legacy code written in UnigineScript as our project was started before the unified API became available in Unigine 2.2. Until 2.9 the code still worked, with only minor adjustments each new release, but now it stopped working and I suspect the delayed deletion added in 2.10 has something to do with it. Is it true that the delete operator in script now redirects the deletion of extern classes to deleteLater? Some of our code relied on widgets being removed from their parent upon their deletion, but now Widget::getNumChildren() returns 1 even after the child is 'deleted'. What makes it worse is that if you use Widget::getChild() on a widget that has been deleted, you get a dirty pointer. The migration guide for 2.10 claims it is safe to call delete twice, but in UnigineScript this will crash: WidgetWindow ww = new WidgetWindow(engine.getGui()); WidgetVBox wv = new WidgetVBox(engine.getGui()); ww.addChild(wv, GUI_ALIGN_EXPAND); while(ww.getNumChildren() > 0) delete widget_cast(ww.getChild(0)); In 2.9 this loop would run once, in 2.10 I would expect an endless loop if delete is delayed, but instead it crashes on the second iteration: Quote ExternClass::destructor(): object is not constructed in "class WidgetVBox * __ptr64" class So did this behaviour indeed change in 2.10? And how can be work around this, is it for example possible to check from script whether a pointer is queued for deletion?
alexander Posted May 7, 2020 Posted May 7, 2020 Hi Bemined, Is it true that the delete operator in script now redirects the deletion of extern classes to deleteLater? Yes, it's true.Is it for example possible to check from script whether a pointer is queued for deletion? Unfortunately, you can't do it now. I've just added a new method to the UnigineScript for this: int is_deleted(pointer). You will be able to use it in 2.12.How can be work around this? I recommend to change your code to something like this: void delete_hierarchy(Widget widget) { forloop(int i = 0; widget.getNumChildren()) delete_hierarchy(widget.getChild(i)); delete widget_cast(widget); } delete_hierarchy(ww); Best regards, Alexander
ExBemined Posted May 7, 2020 Author Posted May 7, 2020 Thanks, we tried deleting the hierarchy like that, but unfortunately there are situations where one or more children were explicitly deleted earlier. We can fix that by calling widget.setParent(NULL) before this delete, but the real challenge is to track down all these deletes, as the crash only happens on the second delete, not the first one. Is this is_deleted a big chance in the source code, or is it a small change we could insert into 2.11 ourselves? We do compile Unigine from source already.
silent Posted May 7, 2020 Posted May 7, 2020 The patch itself is not that big, please check the attach (source/engine/interpreter/Library.cpp). f9028771f20535ee42fc3bcf24a3fe0ac9d16a93.diff.txt How to submit a good bug report --- FTP server for test scenes and user uploads: ftp://files.unigine.com user: upload password: 6xYkd6vLYWjpW6SN
Recommended Posts