Allegro 5 With SWIG and Python
Billybob

I'm building an engine that uses Allegro 5.0.1, and is turned into a Python module through SWIG.

Python:

import IonEngine
IonEngine.init()

In turn, init() is a C function:

void init()
{
     if(!al_init()) {
          printf("Allegro Error: Could not init Allegro.\n");
          return;
     }
}

That works fine. However, when python exits, the DLL crashes. It raises an access violation in (_IonEngine.pyd!_CRT_INIT) at:
onexitbegin_new = (_PVFV *) DecodePointer(__onexitbegin);

If init() is not called, there is no crash. If al_uninstall_system() is called before exiting python, there is no crash.

Besides this issue, Allegro seems to work fine. I can add in display creation, draw some stuff, etc, etc. No crashes until exit.

So I have two options:
1) Figure out why it's crashing, and fix it.
2) or; have Python automatically call the engine's cleanup function.

Does anyone have any ideas as to why the crash is occurring?

_CRT_INIT is apparently called when the DLL is unloaded, and it is responsible for calling all the atexit functions (like the one Allegro registers). I'm not sure what is different between calling al_uninstall_system in _CRT_INIT vs. calling it before Python exits. :-/

Thomas Fjellstrom

Python has probably unloaded the dll before atexit in the CRT is actually called. Or that's what it sounds like.

Billybob

Python has probably unloaded the dll before atexit in the CRT is actually called.

Is that possible? How would python unload a DLL without causing Win32 to fire a PROCESS_DETACH event?

Elias

Instead of al_init I'd use al_install_system, that way you can make sure no atexit calls are made by Allegro.

Billybob

Another detail:

It crashes at d3d_disp.cpp:d3d_shutdown:2656:

_al_d3d->Release();

MSVC correctly reports that it has no idea what _al_d3d is.

So ... I kind of assume the same thing as TF, but I don't know how Python is unloading the DLL without triggering an event, or what I can do to remedy that. In fact, how is it calling d3d_shutdown if the DLL was indeed unloaded?

EDIT: Or perhaps D3D is being killed first?

Elias said:

Instead of al_init I'd use al_install_system, that way you can make sure no atexit calls are made by Allegro.

Yes, perhaps. I can also register an atexit in Python itself. I tested that, and it works. I'm assuming there is a programmatic way to do it on the C side. That's my Option 2 listed in the OP. It's a reasonable solution for this case, but it would be nice to discover the root cause and fix that, so as to assist and future travelers of this path.

EDIT2: Skipping the Release code above, and the bitmap destruction call, results in no crash. So, my best guess for now is that D3D is being unloaded before Allegro and invalidating whatever references Allegro is holding. So ... how do I fix that? :P

Thread #606907. Printed from Allegro.cc