So I've run some serious tracing in the clean environment of IMS2 to track the exact event cue. Here's what happens.
v1 is the vessel calling the integration, v2 is the vessel being integrated
Every new line means a reentering into the dll, i.e. the code has left my little domain and orbiter did some stuff in the meantime.
Code:
event cue on integration:
V1 clbkMouseEvent->triggerRedraw->Assimilate->delete v2
V1 clbkPanelRedrawEvent
V1 clbkPreStep
v2 clbkPreStep
v1 clbkPostStep
v2 clbkPostStep
v1 clbkDockEvent->deldock
v1 clbkPanelRedrawEvent (triggered from dockevent - suboptimal)
v2 clbkDockEvent
v2 ~v2
v1 clbkPreStep
v1 clbkPostStep
As can easily be seen, calling DeleteVessel on v2 doesn't actually delete it... it marks it up for deletion in the orbiter event cue. The vessel goes on existing for a whole frame, and if it was docked it will receive the dockevent (orbiter presumably performes an undocking on the marked vessel prior to deletion. Everything else would, now that I think about it, result in a whole lot of invalid pointers flying around.
More significant in this case is that v1 will also receive this event. As opposed to DeleteVessel, DelDock seems to work practically instantaneously.
It also immediately calls clbkDockEvent if a vessel was docked there... That is, it gets called immediately uppon calling delDock. Although there would still be code to execute in the function. I.E. I suddenly find myself in another place of the code. Since a dock event again triggers a parsing of the docking ports, the whole thing goes into a short kind of recursion, and once I was back where I started things were, quite frankly, not the way they were supposed to be anymore.
To prevent this from happening in IMS2, I had to wait for the vessel-to-be-deleted to undock to delete the docking port savely.
Armed with this knowledge, I took a new look at the old IMS code. It seems I ran into a similar problem there in the past, as I delete the ports
before deleting the vessel. It produces the same problem, however: clbkDockEvent is called virtually immediately, and functions are executed, called from clbkDockEvent,
in the middle of the integrration process that were never meant to be executed.
It is no miracle that this leads to problems. Frankly, I am bloody surprised that it works as well as it does. D3D9 client is a lot more unforgiving, however, so that's where all the crashes came from when I tried to make the thing D3D9 compatible.
I don't know yet how stable the old IMS will be when I fix this behavior, but I'm expecting a rather drastic decrease of CTDs once the thing stops running around wildly on sightseeing tours in the middle of integration...