Hit a `getBackTrace` infloop today

Had a strange getBackTrace hang today. Inconsistently reproducible, and it happens only with an automated VST plugin loader that I use sometimes in live sets. I haven’t been able to reproduce it with simpler, “SC out of the box” code. (I think that’s consistent with other getBackTrace that I recall. It’s very sensitive to specific stack, memory or GC conditions.)

It happened when I was trying to demonstrate something quickly for a student using Vital.vst3, and I didn’t want to create a bunch of MIDI notes by mouse, so I used the \vstVC instrument in my live coding environment. By default, it first loads the plugin, and then if that was successful, it tries to load a preset. I had forgotten to disable the preset-load, so it tried and failed. The \vstVC loader throws an error in case of failure, and this is where it inflooped, chewed up all the RAM in the system, and went into swap space until the system became unresponsive and the only way to get control back was to hard shutdown using the power button.

Just gonna go out on a limb here and imagine that nobody wants this to happen on stage. (Fortunately I wasn’t on stage today.)

The issue reproduced enough times that I could isolate it to getBackTrace.

The complete execution flow in \vstVC is elaborate, but the call stack when it fails to load the preset is short. This is because the failure happens in the server, so from the language’s point of view, it’s asynchronous. The server sends back a message saying that the preset didn’t load, and the language call stack then begins with Main:recvOSCmessage. So, the interpreter’s state shouldn’t have any memory of what was done to trigger the server failure. But, something is stuck in there.

All I can think to do is git bisect, but I can’t reproduce the issue at the moment (yeah… the same reproducer just stopped doing it).

Any ideas? Of course I’ll remove throw from this location and report the failure a different way. Disturbing though.

hjh

What version? I rewrote the debug backtrace primitive a while ago by caching the frames. Before that it could consume a large amount of memory.

Ah right, I forgot to mention. I’m at the Version-3.14.1 tag.

I don’t recall hitting this hang in prior versions, but since it isn’t consistently reproducible, I don’t know if my recollection is important here or not. (Maybe the bug was always there and I just never encountered it.)

EDIT: Checked git log, and found that 3.14 doesn’t have the new backtrace code. Then I went to try the tip of the develop branch (since, remarkably, the issue reproduced again), and ran into a lexer crash.

(gdb) where
#0  0x00005555556e8037 in GlobalBisonLexerState::mutate_global_state_for_return
    (this=this@entry=0x555555a161c0 <global_bison_lexer_state>, o=...)
    at /home/dlm/share/superc-dev/lang/LangSource/PyrLexer.cpp:843
#1  0x00005555556e42e6 in scan_for_end ()
    at /home/dlm/share/superc-dev/lang/LangSource/PyrLexer.cpp:886
#2  0x00005555556e50f3 in parseOneClass (fileSym=fileSym@entry=0x5555568d63c8)
    at /home/dlm/share/superc-dev/lang/LangSource/PyrLexer.cpp:1443
#3  0x00005555556e5a58 in passOne_ProcessOneFile
    (path=filesystem::path "/home/dlm/.local/share/SuperCollider/downloaded-quarks/wslib/wslib-classes/Main Features/SimpleMIDIFile/extSimpleMIDIFile-patterns.sc" = {...}) at /home/dlm/share/superc-dev/lang/LangSource/PyrLexer.cpp:1686
#4  0x00005555556e632a in passOne_ProcessDir (dir=<optimized out>)
    at /home/dlm/share/superc-dev/lang/LangSource/PyrLexer.cpp:1631
#5  0x0000555555733395 in SC_LanguageConfig::forEachIncludedDirectory
    (this=0x555555b30360, func=func@entry=0x5555556e5ae0 <passOne_ProcessDir(std::filesystem::__cxx11::path const&)>)
    at /home/dlm/share/superc-dev/lang/LangSource/SC_LanguageConfig.cpp:88
#6  0x00005555556e3fb7 in passOne ()
    at /home/dlm/share/superc-dev/lang/LangSource/PyrLexer.cpp:1649
#7  compileLibrary (standalone=false)
    at /home/dlm/share/superc-dev/lang/LangSource/PyrLexer.cpp:1795
#8  0x00005555555f0697 in SC_TerminalClient::run
    (this=0x555555b64790, argc=<optimized out>, argv=<optimized out>)

Will have to come back to this later.

hjh

1 Like

Thanks! That’s definitely my code, but it’s the part that compiles the class library, so it’s not related to the getbacktrace issue.

Looks like something odd is going on in wslib/wslib-classes/Main Features/SimpleMIDIFile/extSimpleMIDIFile-patterns.sc.

I’ll try and have a look this weekend.

 if (i==0,Ê

It seems to have an unusual symbols in it (E with a hat) that occurs at random. If you remove them, the issue might go away. Obviously the lexer should handle these - although it’s probably the makeshift parser.

My intent in pointing that out was to explain why I couldn’t test the backtrace problem in dev today. Spotting the difference between backtrace code and lexer code wasn’t so difficult :laughing:

So 3.15 will need a really basic linter for class library and quark files, to drop these characters automatically. Or, maybe the lexer ignores them and posts a warning.

ws-lib is pretty old code, most of it written in the old Cocoa editor I guess. It may not be the only library to have stray non-ASCII characters in places other than string literals.

hjh

Ah I see!

So the lexer does this. The issue is that SC has 3 parser. The main one - this is the one I’ve tested against and works as expected here -, one the builds the class library compilation order - this is the one that fails -, and another that does highlight - also very broken.

I had to rewrite the second one and have probably made a small error regarding invalid utf8.

I’m going to get rid of all of them except the main one because we don’t need 3 that all work with slightly different ideas of what the language is.

I’ll try and get this sorted as soon as possible.

That’s the pr that touched the backtrace code - might solve your issue?