Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Segmentation violation/assertion violation when using stateful functors in interpreted mode #2195

Closed
markusscherer opened this issue Feb 28, 2022 · 7 comments
Labels

Comments

@markusscherer
Copy link
Contributor

Hi!

Problem: When trying to use stateful external functors with the interpreted mode, souffle crashes.

How to Reproduce:

# build souffle according to documentation
# add test.dl and functors.cpp to souffle's root folder
# compile functors.cpp
 g++ -I src/include/ functors.cpp -std=c++17 -c -fPIC -o functors.o
 g++ -shared -o libfunctors.so functors.o
 # execute souffle
./build/src/souffle test.dl

where test.dl contains

.functor mycat(a:symbol, b:symbol):symbol stateful

.decl A(S1: symbol)
.decl B(S1: symbol)

.output A
.output B

A("AA").
A("BB").
A("CC").

B(@mycat(X,Y)) :- A(X), A(Y).

and functors.cpp contains

#include "souffle/SymbolTable.h"
#include "souffle/RecordTable.h"

extern "C" {
 souffle::RamDomain mycat(souffle::SymbolTable* symbolTable, souffle::RecordTable* recordTable,
        souffle::RamDomain arg1, souffle::RamDomain arg2) {
    std::cout << "hallo 1" << std::endl;
    assert(symbolTable && "NULL symbol table");
    std::cout << "hallo 2" << std::endl;
    assert(recordTable && "NULL record table");
//    std::cout << "HHH " << symbolTable->encode("Hall") << std::endl;
    std::cout << "hallo 3" << std::endl;
    const std::string& sarg1 = symbolTable->decode(arg1);
    std::cout << "hallo 4" << std::endl;
    const std::string& sarg2 = symbolTable->decode(arg2);
    std::cout << "hallo 5" << std::endl;
    std::string result = sarg1 + sarg2;
    std::cout << "hallo 6" << std::endl;
    return symbolTable->encode(result);
 }
}

output:

hallo 1
hallo 2
hallo 3
souffle: src/include/souffle/datastructure/ConcurrentFlyweight.h:290: const Key& souffle::ConcurrentFlyweight<LanesPolicy, Key, Hash, KeyEqual, KeyFactory>::fetch(souffle::ConcurrentFlyweight<LanesPolicy, Key, Hash, KeyEqual, KeyFactory>::lane_id, souffle::ConcurrentFlyweight<LanesPolicy, Key, Hash, KeyEqual, KeyFactory>::index_type) const [with LanesPolicy = souffle::SeqConcurrentLanes; Key = std::__cxx11::basic_string<char>; Hash = std::hash<std::__cxx11::basic_string<char> >; KeyEqual = std::equal_to<std::__cxx11::basic_string<char> >; KeyFactory = souffle::details::Factory<std::__cxx11::basic_string<char> >; souffle::ConcurrentFlyweight<LanesPolicy, Key, Hash, KeyEqual, KeyFactory>::lane_id = long unsigned int; souffle::ConcurrentFlyweight<LanesPolicy, Key, Hash, KeyEqual, KeyFactory>::index_type = long unsigned int]: Assertion `Idx < SlotCount.load(std::memory_order_relaxed)' failed.
Aborted (core dumped)

The outputs indicates, that the libfunctors.so is correctly loaded, but that is not possible to reenter the souffle code again.

I instrumented souffle and die pointers to the symbol and record table are passed correctly (i.e. have the same value on the souffle side as on the library side). It makes a difference if encode or decode is used. When when enabling the call to encode in functor.cpp, the output is:

hallo 1
hallo 2
Segmentation violation signal in rule:
B(@mycat(X,Y)) :-
   A(X),
   A(Y).
in file /home/markus/souffle/test.dl

The error also appears with

./build/src/souffle test.dl -c

What works is:

./build/src/souffle test.dl -g test.cpp
g++ -Isrc/include test.cpp -L. -lfunctors -std=c++17 -o test
LD_LIBRARY_PATH=. ./test

but for our use case (for now: executing many smallish test cases) this is unfortunately not too practical. I thought that maybe this has to do with some multithreading problems, but the error also get thrown with -j1.

I first encountered the error on tag 2.2 (and don't no if it ever worked like that) but just reproduced it on a fresh Ubuntu VM with current master (89aae85).

Am I using stateful functors wrong or is this a bug?

@quentin
Copy link
Member

quentin commented Mar 1, 2022

Hi,
Can you make sure the functor library is built with openmp support if the souffle interpreter was too ?
Try adding -fopenmp to the g++ command.

@markusscherer
Copy link
Contributor Author

Indeed, that did the trick! Since that is currently not mentioned in the documentation's chapter on stateful functors: shall I add a sentence or two about compiling them correctly?

@b-scholz
Copy link
Member

b-scholz commented Mar 2, 2022

Please, could you update the documentation? Many thanks in advance.

@quentin
Copy link
Member

quentin commented Mar 2, 2022

I believe we could have some kind of souffle-compile-functors similar to souffle-compile.

Or alternatively we could isolate the SymbolTable interface from the implementation, so that functors only have to know about the interface. I think it's already what was done to isolate the RecordTable.

@b-scholz
Copy link
Member

b-scholz commented Mar 4, 2022

That would be great!

@b-scholz
Copy link
Member

b-scholz commented Mar 7, 2022

I have added a sentence to the documentation about functors.

I thought more about the script. I feel this is tricky because usually, users will have external dependencies. Therefore, I would prefer that build scripts are user-provided.

@b-scholz
Copy link
Member

b-scholz commented Mar 7, 2022

I like the idea of separating the interface. Perhaps we can raise a new issue for this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants