Custom analyzer -- how to interrupt analysis and clean up worker thread?

I’ve got a custom C++ analyzer that for various reasons is very slow (serial protocol, I’m currently outputting too much data, etc). If I remove it from a trace while it’s running and try to re-add it, nothing happens; and I see my analyzer still continuing to run the WorkerThread loop.

What’s the proper way to interrupt this? Is there some notification that the Analyzer went away? I tried adding a flag in my destructor (before the “KillThread”) that I check in the loop, but that doesn’t work (is never set), I assume because the same Analyzer instance is reused?

How does this WorkerThread mechanism work when I have state I’m tracking through my loop? i.e. bits that I’m accumulating. Am I guaranteed a new worker thread per instance of the analyzer? How does the thread actually get killed – is this just pthread_cancel? What if I allocated some temporary objects during the analysis, are these just leaked?

(Warning: minor rant) Also, separately, creating analyzers is super frustrating. The hardware is amazing, and the software is great – but writing custom analyzers is about 1000x more convoluted than it needs to be. Not even basic debug symbols (or frame pointers) seem to be provided for the Logic shared libraries, making debugging basically impossible; I’ve resorted to printf debugging. Documentation is very lacking. The overall analyzer model is just bad and needs to be rethought out. It should be a high level language with quick iteration cycles – there’s already some yet-separate work for the high level analyzers for python; why just “high level”? Or better yet, just expose to javascript; you’re already using electron/chromium to drive the front end, you have everything you could need to build a nice, performant analyzer interface. Contrast all this to how easy it is to create analyzers for sigrok; Logic looks and feels a ton more polished, but sigrok has it beat in this area hands down. (End rant. Sorry guys, I really do love the hardware and software, but man…!)

@vladimirv Sorry for the all the issues with using our Protocol Analyzer SDK!

As far as I remember, this is a known issue. Outside of closing and re-opening the software, I’m not aware of a workaround unfortunately. We should be stopping any threads that are running from a previously added analyzer when removing it. I’ll make sure thing gets brought up with the team here.

With regards to your questions around how WorkerThread works, I’ll get this on the backlog to review with the software team here. We’ve got a few folks out of office, so I apologize for any delays in our reply in advance while your questions are on our backlog.

We appreciate your candid feedback about our Protocol Analyzer SDK as well. We’ve wanted to simplify the creation process with regards to C++ Low Level Analyzers for quite some time now. We’ve tested out a more simplified approach via our Python High Level Analyzers (HLAs) and Measurement extensions with great success so far. This kind of approach is something we’ve wanted to implement with our C++ Low Level Analyzers as well. Having said that, we’ve been absolutely laser focused on other projects for some time. We’re certainly looking forward to implementing improvements like this once we get those projects knocked out.

Tim, thanks for the reponse! Good to know that at least I’m not missing anything. It seems like even with the current design, both problems could be solved with a ShouldContinue() or something function that analyzers are expected to call in their worker thread loop. If the analyzer is removed, or on worker thread cancel, it would provide a clean way to shut down the worker thread.

Also I definitely understand what it’s like to have to focus on higher priority projects even if there’s improvements you really want to make in a less-important area :slightly_smiling_face: Looking forward to hearing more about what you all have cooking up!

Hello,

First off, thanks for the feedback. The C++ Analyzer API is super old, and we are very eager to replace it with something significantly better, but as a tiny team, we can really only focus on one thing at a time. I completely agree that it needs an overhaul, and we have quite a bit of feedback and notes on what we should do next time.

About your current problem.

First, all methods on AnalyzerChannelData internally check to see if analysis should be terminated, each time they are called. We throw a special exception type when this happens, which will cause the thread to exit. The fact that you’re not seeing a clean immediate suggests something is wrong.

Occasionally users will wrap their WorkerThread method with a general try/catch all, which will break this system. Please double check that if you are using try/catch, you are always catching specific exception types. Our exception class does not inherit from any standard exception type, so the only try/catch clause that could catch it is catch( ... )

As long as your analyzer is calling methods on AnalyzerChannelData frequently, the analyzer thread should terminate nearly instantly when removed or restarted.

Additionally, if your analyzer needs to spend significant time doing things other than calling methods on AnalyzerChannelData instances, then you can call the Analyzer method CheckIfThreadShouldExit. This performs the same check, and will throw our exception to terminate the thread when the exit flag has been set.

We catch this exception in the function that calls WorkerThread(). Exceptions will unwind the stack and destroy any objects on the stack in the process, as usual. Generally, latency should be very low, and we’ve tested this with our analyzers extensively. (The easiest way for us to test is to simulate 10 MHz SPI traffic, which produces a huge amount of SPI data and takes considerable time to process, much slower than real time.).