← Back to team overview

yade-dev team mailing list archive

boost::mutex in simulation thread - crash on exit

 

Hi,

It turns out that function fftw_plan_dft(..) from libfftw is
non-reentrant, and I need to guard its call with a mutex. I didn't
discover this until I wanted to add the ability to draw the quantum
wavefunction in momentum representation. Doing this involves calling
FFT transform from the GLDrawing thread, while at the same time (when
the simulation is running) the FFT transform is being called thousand
times per second from the calculation thread. I had numerous crashes
until I added this mutex.

Now with the mutex I have no crashes, and I can look at the running
simulation in momentum representation, FFT being called
simultaneously from both threads. However I got an extra crash upon
yade exit:

boost::mutex::~mutex(): Assertion `!posix::pthread_mutex_destroy(&m)' failed.

This crash happens even when OpenGL window is closed. A mere presence
of this mutex caused it. Even though it was more or less not needed
(no OpenGL drawing going on).

Most helpful here was

http://stackoverflow.com/questions/7817161/boostmutexmutex-assertion-pthread-mutex-destroym-failed

and the last comment: "... the mutex was being torn down before it could be unlocked"


I think that this was the case: the extra mutex that I added had no
chance to close, because the simulation thread was being killed off during
the exit.

I could not find the right place in code to add a call to .join(); to solve this problem.
Instead I changed the Omega::cleanupTemps() by adding stop() call:

void Omega::cleanupTemps(){
  stop();
  boost::filesystem::path tmpPath(tmpFileDir);
  boost::filesystem::remove_all(tmpPath);
}

and now I don't have this crash anymore. I am not sure if that's the best way to do this.

Another option that solved this problem was not introducing a
new mutex, but using the existing one from Omega:
  Omega::instance().renderMutex
But this solution although works, is particularly dirty for me, since
that would require adding to Omega some kind of libFFTWMutex, which
is kind of stupid.


I am not sure how to deal with this, so I wanted to ask for your comments.

IMHO ideal solution would be to put a .join() somewhere, but I am not
sure where it is - maybe somewhere inside python wrappings.

This solution with stop() has just one drawback - if a single
iteration is particularly slow, one will have to wait for it to end,
before exiting yade. Apart from that I think it's a pretty good
solution, and we could decide that calling stop() was simply missing
in cleanupTemps() function and this function should be renamed to cleanup().


Interesting thing - adding this call inside yadeFinalize() instead - didn't fix the crash!

void yadeFinalize(){
  Omega::instance().stop(); // doesn't help!
  Omega::instance().cleanupTemps();
}


best regards
-- 
Janek Kozicki                               http://janek.kozicki.pl/  |


Follow ups