We are seeing a crash in Logic Pro X if the user removes our auwrapper-wrapped plugins any time that the user has clicked in the open plug-in window anywhere, and has not at some point closed the plug-in window prior to removing the plugin.
We are still on VST version 3.6.6, with VSTGUI v4.3. We’re trying to get a product out right away, but this bug is a major sticking point. Because of our tight schedule, we can’t update to the latest SDKs until the next maintenance release (unless we absolutely have to, which will push the release date back quite a while!).
Anyone seen this behavior, and know how to resolve it? (Our older versions, build with VST 3.6.5 and VSTGUI 4.2 under Mac OS 10.10 do not show this behavior, by the way.)
I have experienced this before and it may have to do with the fact that the auwrapper is unloading the executable of the underlying VST3 bundle, which is basically a bad idea when Cocoa/Obj-C is involved. Check About Loadable Bundles where it says “Unloading is limited to applications that do not use the Cocoa runtime environment. At the time of this writing, the Objective-C runtime does not support unloading Objective-C symbols, so Cocoa bundles, once loaded, cannot be unloaded.”
In my case I was encountering a crash when I was removing an au-wrapped instance while my GUI was open.
The workaround was to keep the executable resident by commenting out the following section in auwrapper.mm (starting at line 128):
// workaround, because CFBundleCreate returns refcount == 2.
if (CFBundleIsExecutableLoaded ((CFBundleRef)instance))
Let me know if that helps. I think it should be addressed by Steinberg anyway, as it persists in the latest version of the VST3 SDK.
The latest SDK is what I was referring to, I was quoting the section between #if defined(MAC_OS_X_VERSION_10_11) and #else…so I meant neither have CFBundleUnloadExecutable() nor CFRelease() (unless your VST3 bundle retains itself).
Commenting out that code does indeed stop the crashing!
I’m a little worried about possible side-effects, such as static data, a thread singleton that runs at startup of the VST3 plug-in, and copy protection of the VST3 portion. Is this safe to do in all cases? Could it lead to problems with the items I’ve mentioned?
I’m also curious about your comment about “unless your VST3 bundle retains itself”. Should it? If so, how, exactly?
Sorry for all the questions. I really need to make sure I get this fix right before sending it out into the field.
I wish I still had the link to a technical note by Apple that stated that refraining from unloading the bundle executable in CFBundles that rely on the ObjC runtime is the way to go pretty clearly. Maybe bx_joscha can help out here as we had a similar issue during the development of the PA WPAPI Shell while I was still working at BX and I kept the link in a comment in the source code somewhere.
Side-effects: Well, it basically leads to an unbalanced retain count so it doesn’t behave differently as if an additional instance was still running when you close the last instance of your plugin. Another side-effect is that the library doesn’t have to be re-loaded and remapped once the first instance is/was open, so new instances should open up faster even if all instances were shut down already. Probably that doesn’t count much in the days of SSD and multiple GHz.
If you’re worried about dumping attacks: You could easily trash/restore sensitive data in your singleton during your implementation of DeinitModule() / InitModule()…but someone could still use a e.g. VM to watch the memory regardless of the problem under consideration.
On whether your bundle should retain itself: That would be one possible workaround to defeat the auwrapper’s final CFRelease(). In case of the CFUnloadBundleExecutable() call there is no remedy so there is no way around patching the auwrapper if you’re working with newer base SDKs.
It looks like all that is needed to prevent the crash is to remove that #if clause, allowing it to call only CFRelease, in all cases, rather than removing both calls.
Any reason that solution might cause a problem? It appears that that is what was the original code, and why someone added the “fix” for OS version 10.11, which instead seems to have broken things. I am using the latest SDK, which would be 10.12 (according to both Xcode target settings and a search of the SDKs inside Xcode).
(By the way, the singleton, which spawns a thread that I was worried about not getting shut down, does indeed still get shut down when the last instance of the plug-in is removed, despite the bundle not being released. It depends on the last effect class instance being destroyed, not the bundle being released, so that (and the copy protection) are fine.)
I’m glad I found this thread, I’ve got the same problem with the auwrapper from the VST372 SDK.
When Logic runs M1 native there’s no problem but on Intel or Rosetta I get a crash when removing the plugin, see the crash report below.
Removing CFBundleUnloadExecutable seems to solve the problem, but the plugin stays im memory then - with it’s 2 GB of allocated RAM.
So I’d be glad about a tip how to remove the loaded VST3 plugin crash-free.
Or how to tell the VST3 plugin in DeinitModule() to free the memory.
thanks, Arne. And sorry, I should have come back earlier to report that everything works fine as soon as I disable the “workaround” in auwrapper.mm as suggested above.
It looked like the wrapped VST3 was not deleted, but I simply messed up the memory cleanup code shortly which I didn’t see before.
Btw.: plugins seems to work completely different in Logic running M1 natively than running on Intel/Rosetta. The M1 code starts an additional application called “AUHostingService (Logic Pro)” as a host, which might be the cause for the different behaviour.
The crash in Logic/Rosetta is not the fault of Rosetta, cause it also happens in Logic running natively on Intel.