I am currently developing an audio effect plug-in on Mac, which supports both VST/AudioUnit formats. I am trying to get the plug-in to work correctly in Audition CS6, but I am witnessing some very strange behaviour which is causing crash scenarios.
The problem occurs when I make a call to boost library functions timed_wait() or sleep(). which are called from within a thread I create when the plug-in is first loaded into memory. As soon as one of these methods is called, a crash occurs inside the pthreads library function pthread_getspecific(), due to memory access at address 0x0.
This behaviour is not exhibited in any other host I've tested in. Can you think of any reason why this might be happening?
Thanks in advance,
Audition (and Premiere Pro) uses Boost, so you're probably seeing a conflict between host and plug-in each using separate versions of Boost. We also update our Boost version between releases, so it would be problematic to try and match our Boost version. Other hosts are probably not using Boost yet, so the problem doesn't appear there (yet).
Here's some helpful feedback from one of the Audition engineers:
In theory, the two-level namespace on Mac OS X should solve the problem. It cannot be fixed in the application, only in the library/plug-in.
Here's an explanation:
Thank you for the information on Boost, and the blog post regarding symbol collisions. This came as quite a surprise, as I thought static libs to be immune to this sort of problem. Clearly that isn't the case!
However, I am not fully convinced that namespacing is the problem. I rebuilt both the Boost libraries and my plug-in with the -fvisibility=hidden GCC compiler flag, as directed in the post. This suppressed warnings at link time, but crashing still occurs in pthread API calls when either I load the plug-in or free the instance. I have also seen crashes inside Juce::Thread calls (used for asynchronous updating), which also uses pthreads internally.
In light of this, I am not sure of which way best to proceed. Do you have any other suggestions which might help in solving the problem?
you said that you called the api from a thread.
I've discovered that all the Suite functions are not thread safe (Zac, how about putting that little diddie in the manual??? - I opened probably a dozen tickets and it all came down to the suites not being thread safe)
As a consequence I've put a semaphore around every API call. ("semAdobeSuite")
This has stopped this sort of null pointer crash.
And yes, if you're using static libraries you can absolutely mix versions since your DLL/dylib has absolutely no knowledge of the other other version being used in the executable.
It seems as if two-level namespacing is on by default in OS X. You can only turn it off by passing -flat_namespace argument to the linker.
I have managed to prevent crashing at runtime by replacing a call to boost::sleep_for (which internally involves a pthread call) with just plain old sleep. It doesn't have to be accurate so this is a reasonable solution.
The last remaining issue is the crashing inside the call to thread->join(), which happens in the plug-in dtor. I've managed to catch the following exception from the call:
'boost::condition_variable::wait failed in pthread_cond_wait'
Removing the try/catch around thread->join(), I get the message:
'libc++abi.dylib: terminate called throwing an exception.'
If I try and step through, I can see memory access problems to pthread_mutex_lock().
@Rallymax, I cannot see why wrapping calls to pthread with a semaphore would make any difference here. It seems to me nonsensical how the pthreads library is not thread safe!
Any more suggestions welcome! Thanks,
Just to let you know I've managed to work around the issue by using an alternative callback mechanism, running in the main thread. It would've been nice to find out the root cause of this behaviour, if only I had time!
Thanks for your help.