Logic crash if plug-in removed if editor has been clicked on and not closed

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.)

Thanks,
Howard

Hi Howard,

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))
{
	CFBundleUnloadExecutable ((CFBundleRef)instance);
	CFRelease ((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.

Best,
Ray

interesting i have also seen such things.

in the latest sdk it looks like this:

	~VST3DynLibrary ()
	{
		if (isLoaded ())
		{
			if (bundleEntryCalled)
			{
				if (bundleExitPtr bundleExit = (bundleExitPtr)getProcAddress ("bundleExit"))
					bundleExit ();
			}

#if defined(MAC_OS_X_VERSION_10_11)
			// workaround, because CFBundleCreate returns refcount == 2.
			if (CFBundleIsExecutableLoaded ((CFBundleRef)instance))
			{
				CFBundleUnloadExecutable ((CFBundleRef)instance);
				CFRelease ((CFBundleRef)instance);
			}
#else
			CFRelease ((CFBundleRef)instance);
#endif
			instance = 0;
			isloaded = false;
		}
		gInstance = 0;
	}

are you saying just have CFRelease ((CFBundleRef)instance);?

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.

Thanks!
-Howard

Hi Howard,

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.

Hope this makes sense!

Best,
Ray

Thanks, Ray.

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,

Thomas

Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x00001f79ed97c710
Exception Note: EXC_CORPSE_NOTIFY

Termination Signal: Segmentation fault: 11
Termination Reason: Namespace SIGNAL, Code 0xb
Terminating Process: exc handler [5465]

VM Regions Near 0x1f79ed97c710:
GPU Carveout (reserved) 1000000000-7000000000 [384.0G] —/— SM=NUL reserved VM address space (unallocated)

JS JIT generated code 25eb97600000-25eb97601000 [ 4K] —/rwx SM=NUL

Application Specific Information:
Squire | 9822ba165c8200ad3eea20c1d3f8a51ff3c7a5c38397f17d396e73f464c81ef7 | 6b0f59e988bddaa98489bb219365e5344645b5cf | 2022-04-21_14:22:17

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 libobjc.A.dylib 0x00007fff202f9930 lookUpImpOrForward + 93
1 libobjc.A.dylib 0x00007fff202f931b _objc_msgSend_uncached + 75
2 com.apple.AppKit 0x00007fff22cd4744 -[NSView _removeFromKeyViewLoop] + 60
3 com.apple.AppKit 0x00007fff22cd416d -[NSView _finalize] + 797
4 com.apple.AppKit 0x00007fff22cd3d14 -[NSView dealloc] + 119
5 com.apple.LogicUIKit 0x0000000119352ac5 0x119145000 + 2153157
6 libobjc.A.dylib 0x00007fff20301a04 object_cxxDestructFromClass(objc_object*, objc_class*) + 83
7 libobjc.A.dylib 0x00007fff202fa5a1 objc_destructInstance + 94
8 libobjc.A.dylib 0x00007fff202fa505 _objc_rootDealloc + 62
9 com.apple.LogicUIKit 0x000000011934fb1a 0x119145000 + 2140954
10 com.apple.logic10 0x0000000102120338 0x100fce000 + 18162488
11 com.apple.AppKit 0x00007fff22e5dbb4 -[NSWindowController release] + 130
12 com.apple.CoreFoundation 0x00007fff204f48f8 RELEASE_OBJECTS_IN_THE_ARRAY + 120
13 com.apple.CoreFoundation 0x00007fff204f4839 -[__NSArrayM dealloc] + 280

Have you filed a bug at Apple? As it does not crash natively in Logic I assume that they have a bug in their wrapper code which allows to run intel software on apple silicon machines.

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.