[antlr4] cpp target thread safety

286 views
Skip to first unread message

Josh Chase

unread,
Nov 22, 2016, 8:15:45 PM11/22/16
to antlr-discussion
I've got a rather large antlr4 parser that my company has traditionally used with the C#/Java runtimes. I'm exploring the C++ runtime, but running into problems when it comes to concurrently running instances of the parser.

I have no troubles when I run all of our test cases on a single thread, but when I try to distribute them over a thread pool, things get weird. I end up with segfaults, SIGABRTs, and spurious messages like:
terminate called without an active exception
pure virtual method called
terminate called recursively

When I wrap the parsing/analysis routine in a global mutex so that the parser instances are created one-at-a-time, but on different threads, there are no issues.
In all of these instances, the parser objects never leave the thread on which they're created.


Coming from the Java/C# ecosystems, I expected that separate instances of the parser would not interfere with each other from different threads. Is that not the case in the C++ target or am I doing something wrong?

Mike Lischke

unread,
Nov 23, 2016, 2:57:17 AM11/23/16
to antlr-di...@googlegroups.com
Hi Josh,

When I wrap the parsing/analysis routine in a global mutex so that the parser instances are created one-at-a-time, but on different threads, there are no issues.
In all of these instances, the parser objects never leave the thread on which they're created.

Coming from the Java/C# ecosystems, I expected that separate instances of the parser would not interfere with each other from different threads. Is that not the case in the C++ target or am I doing something wrong?

No, ANTLR runtime classes are inherently not thread safe. This is true for every target language. For better speed there are no synchronizations applied anywhere, except for the shared ATN. There is a mutex to serialize access when a parser attempts to insert new ATN states during preparation of an ATN run. This has been implemented in the C++ target almost the same way as in the Java target.

That means you should never share a parser across threads (or add manual synchronization). Of course it could be that I missed certain situations where we need additional handling. If you can provide a small example that shows a crash where it shouldn't have any problems then open a bug report in the ANTLR repo on Github and I take a look.

Loring Craymer

unread,
Nov 23, 2016, 9:42:54 PM11/23/16
to antlr-discussion
Josh--

Have you wrapped access to the thread pool in a mutex?

--Loring

Josh Chase

unread,
Nov 23, 2016, 11:40:57 PM11/23/16
to antlr-di...@googlegroups.com

That means you should never share a parser across threads (or add manual synchronization).

I'm not actually sharing an instance of the parser across threads - each thread has a separately created parser/lexer/walker. The parsing routine is wrapped in a function that amounts to

 uint8_t parse_string(const char * input) {
    try {
        ANTLRInputStream stream(input);
        MyGrammarLexer lexer(&stream);
        CommonTokenStream tokens(&lexer);
        MyGrammarParser parser(&tokens);

        ParseTree * tree = parser.root();
        ParseTreeWalker walker;
        MyGrammarBaseListener listener;
        walker.walk(&listener, tree);
    } catch (std::exception& e) {
        return 0;
    }
   
    return 1;
}

None of the antlr objects leave the wrapper function, which is what's actually getting run on these threads.

I should also probably mention that this function is being exposed as 'extern "C"' and called by Rust.

I'll see if I can throw together a minimal example that reproduces the behavior I'm seeing - stay tuned.

Edit: Here, check this out: https://github.com/Pursuit92/antlr_cpp_threads


 

Josh Chase

unread,
Nov 29, 2016, 5:19:27 PM11/29/16
to antlr-discussion
Update: I added a c++ version of the code that's giving me trouble.
Not having to jump the FFI barrier should make debugging a bit easier.
Looks like something is getting double freed.

Mike Lischke

unread,
Dec 4, 2016, 8:15:46 AM12/4/16
to antlr-di...@googlegroups.com
Hi Josh,

Update: I added a c++ version of the code that's giving me trouble.
Not having to jump the FFI barrier should make debugging a bit easier.
Looks like something is getting double freed.

Meanwhile we got a bug report for this issue (https://github.com/antlr/antlr4/issues/1435). I'll take care as soon as I can.


Reply all
Reply to author
Forward
0 new messages