On Wednesday, 13 January 2021 at 02:15:49 UTC, Tim wrote:
Basically, the program calls a function which modifies a document in the database. If it is called form it's own class' constructor, it works fine. If it is called by a thread, it never returns.
...
class Caller : Thread{
    void delegate() mFunc;

    this(void delegate() func){
        mFunc = func;
        super(&loop);
        start();
    }

    void loop(){
        while(true){
            mFunc();
        }
    }
}

class Callable{
    MongoClient db;
    Caller caller;

    this(){
        db = connectMongoDB("127.0.0.1");
        foo();
        caller = new Caller(&foo);
    }

    ~this(){
        db.cleanupConnections();
    }

    void foo(){
        writeln("Started");
auto result = db.getCollection("test.collection").findAndModify([
            "state": "running"],
            ["$set": ["state": "stopped"]
        ]);
        writeln(result);
        writeln("Finished");
    }
}

Note that if you are trying to debug a crash or hang of a program by printing messages to the console, you need to flush stdout multiple times in the vicinity of the problem, otherwise stdio's buffering may make it appear as though the program crashed or hung significantly earlier than it really did. (This is not a merely theoretical problem; I trip over it frequently myself.)

Anyway, I think your real problem is that MongoClient is not thread-safe. From the official vibe.d documentation (https://vibed.org/api/vibe.db.mongo.mongo/connectMongoDB):

Note that the returned MongoClient uses a vibe.core.connectionpool.ConnectionPool internally to create and reuse connections as necessary. Thus, the MongoClient instance can - and should - be shared among all fibers in a thread by storing in in a thread local variable.

Note the "in a thread" part; you may only use a connection from the same thread that opened it.

(Why? I'm not familiar with vibe.d's API or code base, so I don't really know. But, I'd guess that the connection reuse mechanism mentioned in the docs requires some of the information that you might expect to be stored in the MongoClient instance itself to instead end up in thread-local storage (whether native or emulated). Or, there may simply be a manual "same thread" check built into the DB operations to prevent data races, and the error message isn't reaching you for some reason. `assert` messages don't print in release mode, and I've found the gdb debugger for D quite unreliable when trying to inspect multi-threaded code.)

Try moving the calls to `connectMongoDB` and `cleanupConnections` into the same thread as `foo`. (I can't think of a good reason to be doing these in the original thread, other than convenience.) If you want to loop in multiple threads simultaneously, just open a separate connection per thread, like the vibe.d docs suggest.

Reply via email to