Page 1 of 2 12 LastLast
Results 1 to 20 of 25

Thread: QT4 and GLib

  1. #1
    Join Date
    Jan 2008
    Posts
    107
    Thanks
    36
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Question QT4 and GLib

    Hi all,

    About Qt4 and GLib ...

    I've written a multi-threaded app with PGSQL support and have noticed that, although having the app heavily and thoroughly scrutinized with the help of Valgrind to cover for any possible memory leaks there's still some segfaults.

    Things I've noticed:
    - the pgsql lib tends to leak...
    - no matter how thoroughly you've debugged your app there's always space for the infamous "double free or memory corruption" crash...

    I've been launching my app preceded with GSLICE=always_malloc and ever since not a single crash yet...
    So I can only assume there's something very wrong with QT and GLib ...

    There also a reference about disabling GLib at http://qtnode.net/wiki?title=Glib_Event_Loop

    So the point here is:
    Should one always resort to the above envvar or simply disable GLib altogether when running multi-threaded apps?

    And more importantly:
    Could someone share his/hers experience and insight in the matter and possibly some tips?

    Thanks in advance,
    Pedro Doria Meunier.

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Thanks
    28
    Thanked 976 Times in 912 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QT4 and GLib

    What do you use threads for?

  3. #3
    Join Date
    Jan 2008
    Posts
    107
    Thanks
    36
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QT4 and GLib

    Hey Jacek,

    Basically for dispatching devices input through sockets...
    One thread per processor (ideally), the others remain queued.
    The idea here is having the tcp socket server as responsive as possible.

    Regards,
    Pedro.

  4. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Thanks
    28
    Thanked 976 Times in 912 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QT4 and GLib

    Are these QThreads? Do you create any objects in their constructors?

  5. #5
    Join Date
    Jan 2008
    Posts
    107
    Thanks
    36
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QT4 and GLib

    Hi Jacek,

    Yes, they're QThreads.

    I create objects, such as QSqlDatabase in their declarations, otherwise there's nothing created in their constructors.


    Qt Code:
    1. class myUnit : public QThread
    2. {
    3. Q_OBJECT
    4. // ...
    5.  
    6. protected:
    7. }
    8.  
    9. myUnit::myUnit ( int socketDescriptor, Server *parent ) : QThread ( parent )
    10. {
    11. // no objects declared here
    12. }
    To copy to clipboard, switch view to plain text mode 

    Regards,
    Pedro.
    Last edited by pdoria; 12th March 2008 at 13:49.

  6. #6
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Thanks
    28
    Thanked 976 Times in 912 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QT4 and GLib

    Do you make any connections between myUnit instance and some other object?

  7. #7
    Join Date
    Jan 2008
    Posts
    107
    Thanks
    36
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QT4 and GLib

    hey Jacek,

    I appreciate you debugging techniques ... and the answer is no.
    However I feel we're missing the point here...

    Point:
    GLib + QT4 still unreliable?

    Personal exp: at least with QApplication it *seems* to be, especially so with QSqlDatabase (PGSQL driver)

    Ever since I switched to QCoreApplication (console-only app) - no more every-week segfaults.
    Yes.. I know... I should have been using it all along...

    Regards,
    Pedro.

  8. #8
    Join Date
    Feb 2006
    Location
    Oslo, Norway
    Posts
    6,264
    Thanks
    36
    Thanked 1,519 Times in 1,389 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Default Re: QT4 and GLib

    Where do you assign to myDB? Be careful, because myUnit::myUnit() and myUnit::run() are executed in different thread context.
    J-P Nurmi

  9. #9
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QT4 and GLib

    Quote Originally Posted by pdoria View Post
    However I feel we're missing the point here...

    Point:
    GLib + QT4 still unreliable?
    Memory leaks don't cause segfaults. If you experience them, it means there is something wrong with your code.

  10. #10
    Join Date
    Jan 2008
    Posts
    107
    Thanks
    36
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QT4 and GLib

    Quote Originally Posted by jpn View Post
    Where do you assign to myDB? Be careful, because myUnit::myUnit() and myUnit::run() are executed in different thread context.
    Hi jpn

    I initialize myDB parameters (and open it) in myUnit::myUnit() .

    Thanks,
    Pedro.

  11. #11
    Join Date
    Feb 2006
    Location
    Oslo, Norway
    Posts
    6,264
    Thanks
    36
    Thanked 1,519 Times in 1,389 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Default Re: QT4 and GLib

    Quote Originally Posted by pdoria View Post
    I initialize myDB parameters (and open it) in myUnit::myUnit()
    Presumably you use it in myUnit::run() too, which means you're using the same database object in multiple threads (which is a no no). The constructor of myUnit is executed in that thread which creates the myUnit object (eg. main thread). However, myUnit::run() gets executed in the "new" thread. For more details, read the detailed description of QThread docs.
    J-P Nurmi

  12. #12
    Join Date
    Jan 2008
    Posts
    107
    Thanks
    36
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QT4 and GLib

    Quote Originally Posted by wysota View Post
    Memory leaks don't cause segfaults. If you experience them, it means there is something wrong with your code.
    Hi wysota,

    Actually I've thoroughly debugged the app using Valgrind. At the end of the (long) run VG reports 0 lost bytes and 0 errors.
    The only (possibly lost) leakage comes from QT's fx members and friends. It's neglectable, however (like 160 bytes or so).

    I've also been running the app with G_SLICE=always-malloc

    Regards,
    Pedro.

  13. #13
    Join Date
    Jan 2008
    Posts
    107
    Thanks
    36
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QT4 and GLib

    Quote Originally Posted by jpn View Post
    Presumably you use it in myUnit::run() too, which means you're using the same database object in multiple threads (which is a no no). The constructor of myUnit is executed in that thread which creates the myUnit object (eg. main thread). However, myUnit::run() gets executed in the "new" thread. For more details, read the detailed description of QThread docs.
    Hi jpn

    This is my myUnit::run
    Qt Code:
    1. void myUnit::run()
    2. {
    3. QString dt = getDateTime();
    4. this->peerAddress = tcpSocket.peerAddress().toString();
    5. textcolor ( DIM, CYAN, BLACK );
    6. printf ("%s: Incoming connection from [%s] - Active clients: %d - DB conn: %s\r\n", qPrintable(dt), qPrintable(peerAddress), server->nbrClients, dbUnique);
    7. textcolor ( BRIGHT, WHITE, BLACK );
    8. exec();
    9. return;
    10. }
    To copy to clipboard, switch view to plain text mode 

    As you can see, no access to the DB here...
    Are you saying that I should initialize the DB in myUnit::run ?

    Thanks,
    Pedro.

  14. #14
    Join Date
    Feb 2006
    Location
    Oslo, Norway
    Posts
    6,264
    Thanks
    36
    Thanked 1,519 Times in 1,389 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Default Re: QT4 and GLib

    So where is myDB used elsewhere than the constructor?
    J-P Nurmi

  15. #15
    Join Date
    Jan 2008
    Posts
    107
    Thanks
    36
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QT4 and GLib

    Quote Originally Posted by jpn View Post
    So where is myDB used elsewhere than the constructor?
    In members
    myUnit::updateUnitRecord
    myUnit::updateUnitHistory

    and only as an argument

    Qt Code:
    1. QSqlQuery query(myDB);
    To copy to clipboard, switch view to plain text mode 

    Thanks,
    Pedro.

  16. #16
    Join Date
    Feb 2006
    Location
    Oslo, Norway
    Posts
    6,264
    Thanks
    36
    Thanked 1,519 Times in 1,389 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Default Re: QT4 and GLib

    And those are called from?
    J-P Nurmi

  17. #17
    Join Date
    Jan 2008
    Posts
    107
    Thanks
    36
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QT4 and GLib

    Quote Originally Posted by jpn View Post
    And those are called from?
    Qt Code:
    1. void myUnit::parseFM4Recs ( quint8 nRecs, QDataStream & records )
    To copy to clipboard, switch view to plain text mode 

    Thanks,
    Pedro.

  18. #18
    Join Date
    Feb 2006
    Location
    Oslo, Norway
    Posts
    6,264
    Thanks
    36
    Thanked 1,519 Times in 1,389 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Default Re: QT4 and GLib

    Ok, remember that we know nothing about all the functions you have in myUnit. I was basically tracking where does the execution come from. A slot? An event handler? It might be easier to track the problem if you provide a little bit more information. Could you perhaps attach myunit.h and myunit.cpp?
    J-P Nurmi

  19. #19
    Join Date
    Jan 2008
    Posts
    107
    Thanks
    36
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QT4 and GLib

    Quote Originally Posted by jpn View Post
    Ok, remember that we know nothing about all the functions you have in myUnit. I was basically tracking where does the execution come from. A slot? An event handler? It might be easier to track the problem if you provide a little bit more information. Could you perhaps attach myunit.h and myunit.cpp?
    Hey jpn,

    I know that and really appreciate all your care.
    As to attaching the code... alas... there are portions of it containing too much proprietary information, which I cannot disclose (protected by NDA).

    The app, however, is a simple one:

    - A new thread gets fired upon an incoming tcp connection
    Qt Code:
    1. void Server::incomingConnection ( int socketDescriptor )
    2. {
    3. nbrClients++;
    4. myUnit *tunit = new myUnit ( socketDescriptor,this );
    5. connect ( tunit, SIGNAL ( finished() ), tunit, SLOT ( deleteLater() ) );
    6. tunit->start();
    7. return;
    8. }
    To copy to clipboard, switch view to plain text mode 
    - I link signals and slots like this (in myUnit::myUnit):
    Qt Code:
    1. // link socket signals to this thread's slots.
    2. connect ( &tcpSocket, SIGNAL ( readyRead() ), this, SLOT ( incomingData() ) );
    3. connect ( &tcpSocket, SIGNAL ( disconnected() ), this, SLOT ( disconnected() ) );
    To copy to clipboard, switch view to plain text mode 
    - this is my incomingData() :
    Qt Code:
    1. void myUnit::incomingData ()
    2. {
    3. QString dt = getDateTime();
    4. short zerocount=0; // number of zero header values to check.
    5. quint16 dataLength=0;
    6.  
    7. unsigned int totalBytes = 0; // quick sanity check...
    8. totalBytes = tcpSocket.bytesAvailable();
    9. if ( totalBytes < 4 ) return; // bogus tx...
    10.  
    11.  
    12. QDataStream inData ( &tcpSocket );
    13.  
    14. while ( zerocount < 4 && dataLength==0 )
    15. {
    16. inData >> dataLength;
    17. if ( dataLength==0 ) zerocount++;
    18. }
    19.  
    20. // sanity checks...
    21. // exceed number of tries... bogus tx. return.
    22. if ( zerocount>3 )
    23. {
    24. cout << "WAY TOO MUCH ZEROES!" << endl;
    25. return;
    26. }
    27. // we wont have packets bigger than this. so it's a bogus tx.
    28. if ( dataLength == 0xFFFF || dataLength==0 )
    29. {
    30. cout << "DATA LENGTH MISMATCH! [" << dataLength <<"]" << endl;
    31. return;
    32. }
    33.  
    34. // wait for a maximum of 5 secs for data...
    35. if (tcpSocket.bytesAvailable() < dataLength)
    36. {
    37. tcpSocket.waitForReadyRead ( 5000 );
    38.  
    39. }
    40. // if 5 secs *still* not enough get out of here!
    41. if (tcpSocket.bytesAvailable() < dataLength) {
    42. this->disconnected();
    43. return;
    44. }
    45.  
    46.  
    47. QByteArray avlData;
    48. avlData=tcpSocket.readAll();
    49.  
    50. if ( !gotImei )
    51. {
    52. checkImei ( avlData );
    53. }
    54. else
    55. {
    56. parseData ( avlData );
    57. }
    58. return;
    59. }
    To copy to clipboard, switch view to plain text mode 
    - This is my disconnected() :
    Qt Code:
    1. void myUnit::disconnected()
    2. {
    3. QString dt = getDateTime();
    4. server->nbrClients--;
    5. textcolor ( BRIGHT, YELLOW, BLACK );
    6. cout << qPrintable(dt) << ": Unit [" << imei.data() << "] disconnected." << " active clients: " << server->nbrClients << endl;
    7. textcolor ( BRIGHT, WHITE, BLACK );
    8. this->quit();
    9. return;
    10. }
    To copy to clipboard, switch view to plain text mode 

    - Upon getting data (using QDataStream), the app simply parses the records contained therein in a loop that calls updateUnitRecord (db use here) and updateUnitHistory (another db use here)

    - After all is done (unit disconnects) the disconnected() fires up and I take care of closing the DB in
    Qt Code:
    1. myUnit::~myUnit()
    2. {
    3. this->myDB.close();
    4. }
    To copy to clipboard, switch view to plain text mode 

    Again, thanks for taking a look at it.

    Regards,
    Pedro.

  20. #20
    Join Date
    Feb 2006
    Location
    Oslo, Norway
    Posts
    6,264
    Thanks
    36
    Thanked 1,519 Times in 1,389 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Default Re: QT4 and GLib

    Well, I'm sorry to say this but you have somewhat severe threading issues there. I strongly recommend reading Multithreading slides from TT DevDays2007 starting from page 33, about thread affinity.
    J-P Nurmi

  21. The following user says thank you to jpn for this useful post:

    pdoria (13th March 2008)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.