Unable to load JUCE plugin .pdb files with Tracktion Waveform

I’m on on Windows 10 using Visual Studio 16.9.0. I can set Ableton Live 10, Reaper, and Renoise, as the debug executable for the VST3 project in VS and launch debugging and see on the debug modules window in VS that when the DAWs load an instance of the plugin, it appears in the loaded modules list, and break points will work, etc.

However, with Tracktion Waveform (versions 11.5.9 and 11.5.17 tested so far), loading an instance of the plugin into the current project/edit results in no module listed in the debug modules window, and no symbols loaded. I’ve tested this a few ways, including just copying the .vst3 and .pdb files from the VS debug build output, straight into the C:\Program Files\Common Files\VST3 folder and debugging from there. Nothing will load the symbols.

I may not be remembering correctly, but I’m almost certain I’ve been able to have plugin symbols loaded in Waveform in the past.

Is anyone else seeing this? Is no one else seeing it? This is a pretty big roadblock to debugging a plugin on Waveform/Windows for me. Any insights appreciated.

Update: It turns out the plugin was sandboxed and therefore prevented from loading symbols.

However, the crash I’m experiencing looks like it’s only happening in sandbox mode. So if loading symbols in sandbox mode is not possible, and the crash only happens in sandbox mode, what are the suggested strategies for successful debugging? Logging to file and hoping to get some meaningful output before the sandbox crash occurs?

To debug the sandbox process you need to attach the Windows debugger to that process (it can be attached to both). I think it’s in one of the tools menus and there should be another Waveform process listed there.

1 Like

Thanks for the heads up. Crash resolved :smiley:

Can I double check what the crash was? Was it something in your code or some different behaviour when using the sandbox in Waveform?

Well, the crash only occurred in sandbox mode, so take from that what you will, but it appeared to be an issue with my code (I’m assuming).

I will try to describe the basic setup:

  • The AudioProcessor plugin has a member instance of a class that runs on a Timer which looks for successful product activation.
  • When activation is detected, an unlock sequence occurs, and invokes an optional std::function<void()> as a callback
  • The plugin’s editor connects a lambda handler to this callback: all it does is set the value of a std::atomic flag to true
  • The plugin editor also has a Timer callback as well, which looks for the flag to be set and handles the unlock event for the editor, which then resets the flag to false, once handled.

In hindsight, it was a bit of a weird setup. I reversed it to a pattern I’ve used before without much issue:

  • The std::atomic flag instead becomes a member of the AudioProcessor plugin class
  • The editor’s Timer callback instead calls a method on the plugin instance that returns the state of the flag, if it happens to be true, it also “consumes it” and sets it to false (internal to the method), and the editor carries out the unlock/activation event for the GUI

Basically in the crashing scenario: the editor owned the atomic flag and its lambda set it to true in response to the AudioProcessor’s licensing checker callback (invoked from a Timer::timerCallback), which resulted in a write access violation when running in Sandbox mode. When the AudioProcessor instance owned/updated the atomic flag instead, and it was just read/consumed by the editor’s timerCallback() there was no issue. Both implementations worked without issue outside of sandbox mode.

I’m not sure how much of that is my sloppy implementation/expected, or how much of that is an unexpected issue, but I definitely don’t have the personal insight to make that call.

Hmm, it sounds like the editor could have been closed and your processor was calling the the now destroyed lambda. The timing might just be different in the sandbox so you didn’t notice it in the normal version.

Your second method seems a bit cleaner to me. Glad you sorted it anyway.