Signal processing seems to be happening during server shutdown

I don’t have enough information yet to log a bug, but I have some evidence of some incorrect server shutdown behavior.

In my MixerChannel quark, I’m trying to stop bad values from going out, like this:

	in = In.ar(busin, 1) * level;
	bad = CheckBadValues.ar(in, post: 0) + (8 * (in.abs > clip));
	SendReply.ar(bad, '/mixerChBadValue', bad, 0);
	badEG = EnvGen.ar(Env(#[1, 0, 1], #[0, 0.05], releaseNode: 1), bad);
	in = Select.ar(bad > 0, [in * badEG, DC.ar(0)]);

Sometimes, not every time, when I recompile the class library, I get a big string of these posted:

BAD VALUES FOUND IN: MixerChannel(hwOut, localhost, 2, 2)
[ /mixerChBadValue, 5, 0, 8.0, 8.0 ]

Dozens of them (meaning the trigger must be flipping between 0 and 8 many many times). The last time, I got 36 messages coming in (not an even division of the block size 64 – so it isn’t just a side effect of a loop – also, 36 > (64/2) so we know that it is not only one control block being processed).

“Bad value” code 8.0 means that the signal is above a preset clip level (not inf, not nan).

Before hitting “recompile,” the server’s signals are completely stable. It’s only at the moment of quitting the server that it starts firing out these OSC messages.

The hwOut mixer is receiving from a few reverb send channels.

[ reverb mixer: synthgroup(empty), effectgroup(reverb synth), fader synth ]
–> [ hwOut mixer: empty groups, fader synth ]

The most obvious guess would be that one or more reverb synths start producing out of range values. But in that case, I would expect the reverb mixer to report the condition – and the reverb mixer’s fader synth should suppress the values, so hwOut shouldn’t report anything. That’s not the case here.

So I have to suppose it might be one of these cases?

  • hwOut’s ‘level’ control bus has an out of range value.
  • hwOut’s audio bus gets garbage data (and the synth is still processing) just before the server really shuts down.

This is only a minor annoyance – the fader synth logic does prevent bursts of noise reaching the speakers. But, what I’m seeing should be impossible if we are shutting down all signal processing before releasing bus memory. Something in the server is processing the SendReply, and the in.abs > clip is getting data from somewhere, at a time when (I believe) all UGens should already have been destroyed. If I’m right about that, then something is not working correctly in the server’s shutdown sequence. That means there’s an uncontrolled situation which, for someone else in another context, might be bad for the equipment.

So I’m curious about this.

Does anyone have other ideas?

hjh

PS Edit: I wonder if it’s that the server’s RT thread gets a callback from the driver, while many but not all UGens have been destroyed. If that’s true, certainly the RT thread should be completely shut down before destroying any units, right?

just some ideas – have you tried debugging this at all? how about trying it with supernova? or on a debug build? maybe running it with a debugger and a breakpoint set to where the server sends replies so you can explore memory at that moment. asan (address sanitizer) or ubsan might help with this too but i don’t think it’s easy to set up right now in our codebase.

are you using DiskIn or VDiskIn? i saw that the plugin containing them has an unload function, and unload functions are called early in World_Cleanup (deinitialize_library()), before stopping audio callbacks.

i would have to read more carefully but some of the shutdown and cleanup logic seems a little complicated; it wouldn’t surprise me if there was a mistake in there.

Hi! I have a question kind of unrelated to op’s which is, how do you use supercollider with a debugger? I and all of the other SC learners I’ve met just lament the convoluted error messages… please let me know!

I’m afraid that my gdb skills end with thread apply all bt. I wouldn’t know how to set a breakpoint :pleading_face:

Not at that time (I seldom use them in general anyway).

A debugger applies only to C++ backend code, not to user code in the SC language. My question is about the server backend so a debugger could be used for that.

There’s an issue logged for debugging in SC language code, but implementing that is very complex. It wouldn’t be soon, I’m afraid.

hjh

1 Like

RMS's gdb Tutorial: How do I use breakpoints? shows how. that whole reference (http://www.unknownroad.com/rtfm/gdbtut/gdbtoc.html) is quite useful in general. you can also set breakpoints in any IDE with a visual debugger.

Ok, thanks. I’ll probably try a visual debugger first. I can see in the doc that it’s very easy to inspect variables in the current scope, but in this case, the data are coming from somewhere else.

I guess the really useful thing would be a conditional watchpoint: break when setting a specific variable to > 1.0 or < -1.0.

hjh

Here’s something interesting: When this happens, the audio in value is nonzero (but very small, on the order of 1e-15), but the clip value (from a control bus) has been set to 0 (before UGen processing is finished). The latter, I wouldn’t have expected – there’s no reason to clear control bus memory while synths are still running.

The audio source, I can narrow down to reverbs. Both FreeVerb2 and JPverb show the symptom.

EDIT: With some debugging printf's in FreeVerb2, I got the missing piece of the puzzle. FreeVerb2’s output is (very slightly) nonzero, even with silent input.

output0 = 9.015405e-15
output0 = 8.900461e-15
output0 = 9.022023e-15
output0 = 8.937258e-15

A bit of -200 dB noise in the signal is not a terrible thing (though I’m a bit puzzled where it comes from).

That means the smoking gun is the fact that the control buses are getting cleared before UGen processing is finished.

World_Cleanup() does Group_DeleteAll(world->mTopGroup); before delete hw->mShmem; but I wonder if it’s possible that the node tree isn’t completely gone at that time.

Anyway, I think I can put some kind of guard in and prevent the mixer channel warning.

It’s probably not a critical issue to fix – but, interesting that there’s this sync issue during shutdown.

hjh