Where exactly does the application crash? What does the debugger say?
sylvaticus (3rd July 2009)
Sorry for the late response (I moved to an area without internet :-( ).
The application crash when I use a call to a mathematical programming library named "glpk".
"Program received signal SIGABRT (Aborted)"
// solving the problem with the integer variables
stat=lpx_integer(lpglpk);
The re-entrant capability of this library is not assured, but the point is that it is wholly called from agent->cachedOffer = agent->offerRentalPrice(plot); that is protected by a mutex.
By the way all the steps of solving the mathematical problem (initialise the problem, solving, getting the solution and deleting the problem) are done within the "offerRentalPrice()" function.
So my question is: why even if I place a mutex this function is executed concurrently?
Please introduce debug statements around locking and unlocking the mutex so that you can check the sequence of the calls. You can use QThread::currentThreadId() to provide information which thread is performing the lock/unlock operation.
I put debugging messages around the two lock/unlocks:
Qt Code:
void Manager_farmers_threads::run(){ int threadId = currentThreadId(); cout <<"A "<<threadId<<endl; mutex->lock(); cout <<"B "<<threadId<<endl; ( (Agent_farmer*) agent)->cachedOffer = ( (Agent_farmer*) agent)->offerRentalPrice(plot); cout <<"C "<<threadId<<endl; mutex->unlock(); cout <<"D "<<threadId<<endl; }To copy to clipboard, switch view to plain text mode
I'm attaching the output log...
This is an other log with only ABCD:
The external library crash only if I use nThreads > 1.************************************************** *****************
*** !! Welcome to RegMAS - Regional Multi Agent Simulator !! ***
*** For info & doc: http://www.regmas.org/doc ***
*** Compiled on: Jul 3 2009 - 14:10:18 ***
************************************************** *****************
Selected scenario: default
**WARNING: No elements in the XML file. Expected at least one of type reclassRule
**WARNING: No elements in the XML file. Expected at least one of type reclassRule
ABCDABCDABCDABCDABCDABCDABACDBCDABCDABACDBCDABCDAB ACDBCDABCDABACDBCDAB
Furthermore, the second log were generated using the original, non-safe library, while the first log - crashing much later during the execution - were generated using a dev version of that library that is going in the direction of thread-safe.
So my question is: if I have a thread-unsafe library and I try to access it from different threads, even if I access it in a serialised way (using mutexes), it could be any how dangerous.
Is this sentence correct?
It seems that locking works fine. If the library uses some internal static data, the data might become corrupted if it is overwritten with another cycle of a function that operates on the data before the data is actually used somewhere. But it is impossible to determine that without knowing the structure of the library. You might try debugging the library itself.
I managed to create a test case where I don't use any mutex, just a SINGLE separate thread that call the external library (glpk) solving an example problem.
I use this thread in a loop that assigns new jobs to it when it is not busy.
Glpk crashes when comparing the elapsed time using CPU clocks.
The glpk maintainer told me that he doesn't think it is a glpk bug, so I am last with a problem either in my code (very likely) or in the QT thread library.
You can find attached a small test case, but the core of the issue is in the above code:
Qt Code:
#include <glpk.h> #include <Thread.h> using namespace std; int main(int argc, char *argv[]){ cout << "Test on glpk using Qt Threads" << endl<<endl; Thread wThread; // a simple subclass of QThread for (uint y=0;y<500;y++){ bool assigned = false; while(!assigned) { if (!wThread.isRunning()){ wThread.start(); // job done from the other thread. Just solve a simple linear programming problem (glpk documentation example) assigned = true; break; } } } cout <<"All done without errors (crashing)"<<endl; return 0; }To copy to clipboard, switch view to plain text mode
Am I doing something very naif???
I managed to retrieve the error also doing a more simple loop:
Qt Code:
int main(int argc, char *argv[]){ cout << "Test on a glpk application using Qt Threads" << endl<<endl; Thread wThread; for (uint y=0;y<5000;y++){ wThread.start(); // job done from the other thread wThread.wait(); } cout <<"All done without errors (crashing)"<<endl; return 0; }To copy to clipboard, switch view to plain text mode
The error I have from glpk is:
I really do not understand why this external library crash if I put it on an external thread that I run consecutivly while it works whitout problems if I run it in the main thread.Assertion failed: xlcmp(env->t_last, t) <= 0
Error detected in file glplib10.c at line 109
It seems a Qt bug (but of course, I'm not sure..)
http://bugreports.qt.nokia.com/browse/QTBUG-684
I don't think the bug report has anything to do with your code. The fact that you do use wait() and you do use threads doesn't mean the situation is the same as the one you described. It all depends what your thread does. Anyway you can make a workaround that the main thread waits on a dedicated wait condition. Another thing is whether it makes any sense to do something in another thread if you just block the main thread until it is finished. A producer-consumer pattern looks totally different than your code, above all it doesn't have any while loops.
hello, in fact this code is also not working:
The idea is to have a vector of threads doing the jobs simultaneously and for doing this I will need a patched version of the glpk library, but I stopped when I noticed that even when I use a single thread I have problems.Qt Code:
Thread wThread; // a simple subclass of QThread for (uint y=0;y<500;y++){ bool assigned = false; while(!assigned) { if (!wThread.isRunning()){ wThread.start(); // job done from the other thread. Just solve a simple linear programming problem (glpk documentation example) assigned = true; break; } } }To copy to clipboard, switch view to plain text mode
Then I tried to put the example on its minimum terms.
The Thread::run() function just does something like:
Qt Code:
for (uint i=0;i<3;i++){ glp_prob *lp; lp = glp_create_prob(); [...] glp_load_matrix(lp, 9, ia, ja, ar); glp_simplex(lp, NULL); [...] glp_delete_prob(lp); }To copy to clipboard, switch view to plain text mode
This code works if I call it directly in the main thread (that really in the real application is itself a working thread separated from the GUI), but crash when called from wThread. I thought that even if the bug report refers to the "wait()" function, the cause underlying it would be the same causing the problem in my situation.
From what I see you are trying to start 500 threads using the same thread controller object. This is simply bound to fail.
Try this:
Qt Code:
class MyRunnable : public QRunnable { void run(){ for (uint i=0;i<3;i++){ glp_prob *lp; lp = glp_create_prob(); [...] glp_load_matrix(lp, 9, ia, ja, ar); glp_simplex(lp, NULL); [...] glp_delete_prob(lp); } } }; //... for(int i = 0; i<500; i++){ QThreadPool::globalInstance()->start(new MyRunnable); }To copy to clipboard, switch view to plain text mode
You can call this before you enter the loop to make sure only one thread at once is ran:
Qt Code:
QThreadPool::globalInstance()->setMaxThreadCount(1);To copy to clipboard, switch view to plain text mode
sylvaticus (4th December 2009)
Thank you.. this method is working. However, I tried debugging my first code (those with the isRunning() check) with QThread::currentThread() and I noticed it was producing only two threads (one main and one working) as expected, not 500, so I still don't know why it wasn't working...
Bookmarks