Crashes with juce::dsp::Convolution & juce::dsp::Queue

I’m having some problems with juce::dsp::Convolution & it’s queue.

I’m sharing a one convolution queue instance with many Convolution instances.

Everything seems to work well but not in OS X Mojave & Auval tool.

I’m getting crash reports from my users that auval crashes during the processBlock when Convolution is loading new IR (as instructed on the documentation, loadImpulseResponse method)

Unfortunately I can not reproduce this on my development machine so I’m just getting information from resymbolicated reports.

On the call stack I see following lines:

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

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

juce::dsp::Queue<juce::dsp::FixedSizeFunction<400ul, void ()> >::push(juce::dsp::FixedSizeFunction<400ul, void ()>&)

juce::dsp::Convolution::reset()

Do you have any idea what might be the problem?

The queue must stay alive for the entire time that Convolution instances are alive. Perhaps the queue is being destroyed while there are still Convolutions in use - perhaps stick a breakpoint in the destructor of the ConvolutionMessageQueue and the Convolution and check that the ConvolutionMessageQueue is destroyed last.

You should also make sure that you’re calling loadImpulseResponse with appropriate synchronisation (i.e. either in prepareToPlay, or in processBlock).

If you’re still encountering issues after this, you could try debugging in Pluginval with the Address Sanitizer enabled. Hopefully that will give you a more descriptive stack trace which will help to pinpoint the issue.

Thanks a lot @reuk

The queue is a member data in my utility class which is instantiated as Juce’s singleton. It’s destructed in the AudioProcessor’s destructor.

loadImpulseResponse method is always called in the processBlock method.

The biggest problem is that I can not reproduce or debug this on my own setup, I only get crash reports from my users. And it seems that they are only coming from OS X Mojave & auval tool.

Is it destructed before or after the convolution instances?

Thanks, I need to check that. However, the crash happens during the processBlock() method. Would it be possible that the instance of AudioProcessor class is deleted while it still gets calls to processBlock() on another thread? Wouldn’t make much sense.

You’re right, that does sound unlikely.

How are you destroying the singleton in the destructor of the AudioProcessor? Is it possible that if there are two AudioProcessors active, destroying the first processor might also destroy the queue that is still being used by the second AudioProcessor?

If that’s not the problem, I’d recommend testing your plugin with Pluginval after building both with Address Sanitizer enabled. If there are lifetime-related issues in your program, Asan/Pluginval should help you to find these problems.

Thanks for your kind help @reuk in this matter. I really appreciate it.

I don’t think that’s the problem. I’m using deleteInstance() method to delete it. I also quickly tested by removing the deletion and the same problem still occurs.

I managed to get an old laptop which I can now use to reproduce this error. And now I have a better call stack of this error. Unfortunately I don’t fully understand what’s going on the Convolution dsp code.

Here’s a screenshot of the callstack.

You should see a large amount of output in Xcode’s Console window when you encounter an Asan error like this. Could you paste that output please?

Yes, I get that but unfortunately it contains my customer’s classified information. Is there a specific part which would be helpful to you? I could then censor the classnames etc.

The screenshot tells you that you’re using some memory after it’s been freed. The console output should tell you where this memory was freed, so you can look at the stack trace at that point, and maybe try sticking some breakpoints in the mentioned functions so that you can see the order of calls which causes the problem.

I also notice that you’re calling loadImpulseResponse from the message thread, which might be part of the problem. If loadImpulseResponse is called from the message thread while processBlock is called on another thread, you may encounter data races, resulting in undefined behaviour. It’s probably worth looking at the call stack in the screenshot you posted, and removing the call to loadImpulseResponse from the message thread at this point.

OK, I’ll need to learn to read that output properly :slight_smile:

Thanks a lot. I’m still doing some tests with the deleteInstance() method. Actually there might be something there.

IDK if the thread name is something not usual because of the auval. On the bottom of the call stack there is a call to processBlock, However I have run tests both ways, by loading initial ir on the prepareToPlay method and also only on the processBlock method. The result is always the same.

The good thing is that I now have a env where I can reproduce this.

OK,

This is embarrassing to say but in the end the problem was in the deletion of the message queue.

Older version of auval actually creates multiple instances of the AudioProcessor and when I deleted the singleton instance on it’s destructor *hit hit the fan big time.

Big thanks to @reuk for helping here.

1 Like

Thanks for the update, glad you got to the bottom of it!