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.