Help: Problems running the plugin in UAD Luna

Hello everyone, this is my first post here.

I’m developing my first plugin (A/B reference utility). With some effort, I managed to finish and successfully run it in some DAWs (Sonar and FL Studio). However, when testing it in the UAD Luna DAW, the plugin exhibits a strange crash behavior.

When placing the plugin in the channel insert, it simply closes on its own along with the DAW. I tried using AI to solve this, but it didn’t work.

In some tests, the plugin worked in headless mode (without visual components, only the audio logic), but when adding timers, or components from the JUCE itself, or binary PNGs, the plugin starts showing the error again.

I’ve already checked the Luna logs and used debugger tools to find the error, but nothing indicates what’s actually causing it. My suspicion is something very specific to the GUI, but I have no idea what it is since it passes the Val plugin tests, SDK Validator, and GUI Stress tests with 100% success.

Can anyone help me?

(Note: I’m trying to run the plugin in VST3 within Luna since it now has support and even very old plugins can run in the DAW)

In some tests, the plugin worked in headless mode (without visual components, only the audio logic), but when adding timers, or components from the JUCE itself, or binary PNGs, the plugin starts showing the error again.

Sounds like a thread safety issue to me. What does the crash log say?

  • Do you declare anything static (but should not be static) in the UI part?
  • It seems that the UI should not read too much stuff from the processor. Do you read the RMS level in a thread-safe way? Do you handle parameter updating in a thread-safe way?
  • Have you used ThreadSanitizer with pluginval to test it? Does it provide anything useful?
1 Like

Hello, thank you for taking the time to respond. Based on your questions.

I conducted an extensive analysis of the code, and here are my findings:

Regarding static elements in the GUI: I am using only static constexpr in LabelSmoothingData and CorrelationMeter. As for thread safety of RMS, they are read via std::atomic::load() on the UI thread, and parameters are accessed through AudioProcessorValueTreeState::Listener combined with AsyncUpdater, with caching implemented via std::atomic.

I have not yet run ThreadSanitizer on pluginval to collect logs; I will test it today. Meanwhile, the general logs from pluginval and the SDK validator indicate everything is functioning correctly. The LUNA logs only record the moments when the plugin opened and closed, confirming that the editor was opened, but they do not indicate any errors. I attempted to analyze further using the system’s DebugView, but no issues were detected.

If all other debugging methods fail then you can try commenting out code until you can spot the issue. It’s tiresome, but it works. For instance, you could start by commenting out everything in the processBlock and prepareToPlay functions. If it runs without crashing, then start un-commenting out code until the crash comes back.

You are correct—it is indeed an archaic and tedious method, yet it remains the most effective for locating and isolating the conflicting object. Should debugging analyses prove insufficient, I will conduct an exhaustive review and return with feedback upon identifying the error.

Well, several days have passed, and I am still grappling with the same issue. I have been systematically reviewing portions of the code in search of the plugin’s potential problem, and I have arrived at this interface result:

the plugin continues to crash within the DAW Luna. On occasions when it does not crash, the GUI fails to load entirely, displaying only a black background.
Summary of this build:
Editor disabled,
minimal DSP,
bypass functionality,
and exclusion of resource-heavy UI components.

Have you tried the following?

  • Build your plugin in the ‘debug’ configuration
  • Launch UAD Luna and start a new/blank project
  • In your IDE, use the “Debug” menu to “attach” the debugger to Luna (this should be possible in Visual Studio and Clion)
  • Now, add your plugin and carry out whatever other steps are necessary to provoke the crash

If the program crashes, you should see that the debugger pauses to show you the stack at the point of the crash. This might give you some clues as to the root cause. If not, you can try sharing the stack trace here to see whether anyone else can guess at the problem.

As a last resort, if you’ve minimised the failing plugin example as much as possible, you could share the code here to see whether anyone else is able to reproduce the same behaviour, and potentially debug it.

Hello everyone, I return once more to this topic to finally announce that the error has been resolved, and the plugin now runs flawlessly within DAW Luna. I must confess that I enlisted the assistance of the AI Gemini 3 to conduct a thorough analysis and resolve the issue—successfully, I might add. Since I was uncertain of the precise nature of the problem, I requested that it generate a detailed .md file documenting both the error and its resolution.

I shall share this with you all, and in advance, I extend my heartfelt gratitude for the time and effort you devoted to helping resolve this matter. Thank you profoundly.

# Analysis and Correction Report: UAD Luna Crash

**Problem:** Crash when inserting the plugin into UAD Luna (Black screen followed by DAW closing after ~2 seconds).

## 1. The Identified Problem

The plugin worked correctly in more permissive DAWs (Reaper, FL Studio), but failed catastrophically in UAD Luna. The symptom of a "black screen" followed by a quick crash is characteristic of two types of critical failure:

1. **Watchdog Timeout:** The DAW detects that the plugin has blocked the audio thread or the interface thread for too long and terminates the process to protect itself.

2. **Memory/Stack Violation:** Misuse of memory that corrupts the program state.

Our "surgical" analysis of the code revealed two serious root causes that, combined, caused the instability.

## 2. Technical Diagnosis

### A. Real-time Violation in the Audio Thread

**Where:** `PluginProcessor.h` / `PluginProcessor.cpp` (LoudnessWindow and IntegratedGating structures)

**The Error:** Use of `std::deque` within the `processBlock` method.

**Explanation:** The `std::deque` container (and `std::vector` if resized) performs dynamic memory allocation (`malloc`/`new`) when new elements are added.

**Why does Luna crash?**

UAD Luna (and Pro Tools) has extremely strict real-time requirements. In digital audio processing, the audio callback (`processBlock`) must execute in microseconds. Allocating memory is a "non-deterministic" operation (it can take a long or short time). If the plugin attempts to allocate memory and the operating system takes too long to respond, the plugin misses the audio delivery deadline (buffer underrun). In severe or repetitive cases, this causes memory instability or stack overflow, leading to a crash.

### B. Message Queue Flooding in the GUI

**Where:** `PluginEditor.cpp` (`timerCallback` and `ensureLabelsAbsoluteFrontAsync`)

**The Error:** Call to `juce::MessageManager::callAsync` 60 times per second.

**Explanation:** The `timerCallback` method was attempting to enforce the overlapping order (Z-order) of the "A/B" labels using an asynchronous call every frame.

**Why does Luna crash?**

The `callAsync` method places a message in the operating system's event queue to be processed "as soon as possible". By doing this 60 times per second, the plugin flooded the message queue of the main thread (UI Thread). When Luna UAD attempted to draw its own interface or communicate with the plugin, the queue became congested. This resulted in the interface freezing (black screen) and eventually, the operating system or DAW terminated the plugin due to lack of response (App Hang).

3. What UAD Luna (and Professional DAWs) Require

For a plugin to run stably in professional environments like UAD Luna, Pro Tools, and Nuendo, it must strictly follow the **Real-time Safety** rules:

1. **Zero Allocations in the Audio Thread:** Never use `malloc`, `new`, `std::string`, or resize containers (`std::vector::push_back`, `std::deque::push_back`) within `processBlock`. All memory should be allocated in `prepareToPlay`.

2. **Clean UI Thread:** The interface thread should not be blocked or flooded. Heavy operations should be performed in background threads, and communication should be efficient.

3. **Determinism:** The audio code should always take the same time to execute, regardless of the input data.

## 4. Implemented Solution

We performed a focused refactoring to eliminate violations without altering the plugin's functionality.

### Fix 1: Static Circular Buffer (Audio Thread)

We replaced the dynamic `std::deque` with a **Circular Buffer** based on pre-allocated `std::vector`.

* **How ​​it works:** In `prepareToPlay`, we allocate all the memory needed for 20 minutes of LUFS measurement.

* **In processBlock:** We only write to the pre-existing vector indices, rotating the write index.

* **Result:** Zero memory allocation during playback. Constant and predictable CPU load.

### Fix 2: GUI Optimization (UI Thread)

We completely removed the `ensureLabelsAbsoluteFrontAsync` mechanism.

* **Action:** We eliminated calls that were flooding the message queue.

* **Adjustment:** The order of elements (Z-order) is now correctly set only when necessary (in the `resized` method or when there is a real state change), and in a synchronous and efficient way.

* **Result:** The UI thread is free to render the plugin and respond to the DAW, eliminating the black screen and freezing.

**Final Status:** The plugin now adheres to strict VST3/AU development standards, ensuring compatibility with UAD Luna and superior stability in all DAWs.