I'm working on updating the OpenAL Soft port to version 1.13 but I'm having some problems with the shared object.
If I link and run utils/openal-info using the static libopenal it runs without problems (doesn't matter if I use static or shared other libraries). If I link it with libopenal.so it either ISIs on alcOpenDevice() or works correctly but hangs on exit depending on whether I use -nostartfiles when creating the .so or not.
All the object files for the .so are compiled using -fPIC option so at least that's not what is wrong.
Modified source code including Makefile used for compiling can be downloaded from here:
http://dl.dropbox.com/u/26599983/openal-1.13-os4.7z
Unless I completely misundertsnd what you are doing you should not be using -nostartfiles at all, you should be using -shared.
BTW blender crashes on exit, after a prolonged video edit, and I believe OpenAL is a possible reason, it's gard to be 100% sure, but it's an interesting cooincidence.
I've just downloaded your source I will take a look....
ouch! :-)
Try
You don't want -nostartfiles as -shared implies parts of -nostartfiles that you need and draws in the sharedobject startup code, which -nostartfiles will exclude. As it's later on the command line it probably undoes the -shared option.
-use-dynld is for building apps not libs. It may or may not make any difference I don't know.
On the other hand if you library is incomplete and you don't specify "-Wl,--no-undefined" you will never get an error or warning about any missing symabol / function it will just crash at run time.
ppc-amigaos-gcc -mcrt=newlib -shared -Wl,--no-undefined -o libopenal.so OpenAL32/alAuxEffectSlot.lo OpenAL32/alBuffer.lo OpenAL32/alDatabuffer.lo OpenAL32/alEffect.lo OpenAL32/alError.lo OpenAL32/alExtension.lo OpenAL32/alFilter.lo OpenAL32/alListener.lo OpenAL32/alSource.lo OpenAL32/alState.lo OpenAL32/alThunk.lo Alc/ALc.lo Alc/alcConfig.lo Alc/alcEcho.lo Alc/alcModulator.lo Alc/alcReverb.lo Alc/alcRing.lo Alc/alcThread.lo Alc/ALu.lo Alc/bs2b.lo Alc/mixer.lo Alc/panning.lo Alc/ahi.lo Alc/null.lo -lpthread
Alc/ahi.lo:(.got2+0x4): undefined reference to `IExec'
removing -Wl,--no-undefined it builds.
I'll come back after I've tested ...
Hmmm hangs on exit....
I only added -nostartfiles because it wasn't working without it and I had some memory that I read somewhere that you needed to add it when creating a shared object to stop normal startup code being linked in (I probably remembered wrong though), I didn't know that there is special startup code that is linked only into shared objects.
I guess it might be implied by the -shared option but I don't think it hurts to be explicit, which is why I have -mcrt=newlib even though newlib is the default c-library. Anyway I was somewhat under the impression that you always needed to specify -use-dynld if you wanted gcc/g++ to be able to link with shared objects.
I've put updated source code with your suggested changes added at the same link, but as you've already noticed even with these changes the shared object still doesn't work (hangs on exit).
Did you try to link with -Wl, --export-dynamic option?
I had a similar problem wih iodbc shared object. and indeed without that option i get ISI every time.
I did try -Wl,--export-dynamic when linking openal-info but it didn't make any difference.
-noatartfiles is required for amiga shared libraries not shared objects.
Yes. I tried a few things and can't se what the issue is. It seems to hang after main has exited.
I rebuilt openal for blender (perhaps for this very reason, but I can't really remeber why) and the libopenal.so with blender doesn't not crash on exit. I can't for the life of me remeber what was changed...
Looking at the 'crashed task' in Scout it appears to be waiting on semaphore signal. That doesn't mean for certain that it's really a semaphore as Scout bases that assumption on the particular signal number IIRC.
If I send the signal it's waiting for (0x0000010 4) then I get a crash.
As far as I can see then
alc_init and alc_deinit are setup as a constructor / destructor pair.
lines 383 384 in ALc.c
I can't see the explicit call to pthreads in those functions, but I guess it's traced through to a called function deeper down.
I'm guessing then when linked as a shared object the pthread.so destructor get's called first. Thus causing the crash. When linked staticaly the destructor will get added to the main executables construtor list and thus get called before the pthread destructor.
Note that may not be guaranteed if you link wholy statically with libpthread.a as then the construtor order may not be guarenteed any more.
I think to make a viable and safe openal under AmigaOS you will need to remove the constructors and explictly call the functions and start and finish of the program.
I just tried that solution and it solves the problem but it also means that every ported program that uses openal needs to be modified to add these acl_init() and acl_deinit() calls manually, and of course then there is also the matter of programs that use openal through another library like freealut, I guess there might be the same problem with constructors/destructors here too and even more such changes need to be added to those programs. I can't say that I'm too happy about this (how come linux and other OSes that use shared objects don't suffer from this problem with openal or other libs for that matter?).
Ah you beat me to it.
I've built a version that works too making the modification.
I've come across a few places that make assumptions about pthreads. The linux implementaion is clearly different and many apps from the linxu world simply assume that it exists and is ready to use. The same assumption can never be true of AmigaOS (well unless pthreads were built into the kernel in some way I suppose).
OpenAL is the first program I've come cross that makes such a large usesage of consructors in a shared object. The other time I've come across this issue was with C++ constructors with static objects.
An alternate solution to modifying apps to call alc_init() and alc_deinit() would be to modify alcCreateContext to call it on first invocation.
something like
static WORD inited = 0;
alcCreateContext()
{
if(inited++ == 0)
{
alc_init()
}
}
alcDestroyContext()
{
if(--inited == 0)
{
alc_deinit()
}
}
That assumes that you must always call CreateContext to use openal I don't know much about OpenAL so that may not be the case.
BTW I'm not 100% that constructor / destructor call order is the culprit yet, but it's my best guess,
It probably is. I remember Spot and me had a similar problem with destructor order during the porting of Black Shades Elite (an FPS where you play as a psychic bodyguard), only in that case the problem was with minigl destructor and not with pthread one. The "solution" we ended up using was AFAIR far from an ideal one.
Adding alc_init()/alc_deinit() to alcCreateContext()/alcDestroyContext() won't work I think. Adding them to alcOpenDevice()/alcCloseDevice() might work for most programs but probably won't be a perfect solution either but still better than nothing I guess.