Am 23.04.2012 08:52, schrieb David:
Am 23.04.2012 08:41, schrieb Benjamin Thaut:
I wrote a small "bad example" program for a presentation. It calls
malloc/free very frequently and I wanted to profile the impact of this
compared to a pool allocator solution. Unfortunately I had to notice
that the program only runs for a fraction of a second before
deadlocking. As it seems the following situation accurs:

1) Thread 1 calls malloc(), and locks the internal malloc mutex
2) Thread 2 triggers garbage collection and stops thread 1
3) Thread 2 is done collecting garbage and calls all destructors. One of
these calls free(), as the malloc mutex is still locked by Thread 1 and
Thread 1 will never release the mutex, as it is stoped, Thread 2
deadlocks.

Now this is not limited to malloc / free, it can happen with any kind of
locking that is done within a destructor.

Currently I can only think of two ways to fix this:

1) Don't use free inside a destructor (goodbye manual memory management)
2) A callback triggered by the GC before it starts stopping any threads,
and after it is done destructing all objects to manually lock / unlock
necessary synchronization primitives to prevent this kind of
deadlocking. The default implementation of this callback should lock /
unlock the malloc mutex.

That's nearly the same with OpenGL, never, really never put a
glDelete*-Call in a Dtor, I had this for a few commits in glamour (a
OpenGL wrapper) and it kept raining Segfaults.
The bigger problem was, that was only caused by the GC, I didn't tell
him to collect garbage from another Thread, it happend when it jumped
in, and called dtors.
The way I have fixed it was with "scope" and an additional .remove
method. Maybe this is the way you can solve your problem.

Well the issue with OpenGL is that you can only make OpenGL calls from the thread that actually owns the OpenGL context, so this is not quite the same. Because I'm perfectly allowed to call free from a different thread then where I called malloc. Also this is not only my problem, std.container.Array uses malloc & free so it can happen there too.

Reply via email to