Results 1 to 5 of 5

Thread: removeAll not working

  1. #1
    Join Date
    Jul 2006
    Posts
    3
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default removeAll not working

    I am developing a server application that receives commands from client applications through TCP. To create the server, I derived a class called MyTcpServer from QTcpServer and in this class I reimplemented the QTcpServer::incomingConnection( int socketDescriptor ) method so that it creates a MyTcpSocket (derived from QTcpSocket) and adds a pointer to this object to a QList. The reason I store a list of all the MyTcpSockets is that I sometimes need to send a message to all clients.

    Here's the significant part of my MyTcpServer class:
    Qt Code:
    1. class MyTcpServer : public QTcpServer
    2. {
    3. Q_OBJECT
    4.  
    5. public:
    6.  
    7. MyTcpServer( QObject* parent, const QHostAddress& address, quint16 port )
    8. : QTcpServer( parent )
    9. {
    10. listen( address, port );
    11. }
    12.  
    13. QList<MyTcpConnection*> clients()
    14. {
    15. return _clients;
    16. }
    17.  
    18. protected:
    19.  
    20. void incomingConnection( int socketDescriptor )
    21. {
    22. _clients.append( new MyTcpConnection( this, socketDescriptor ) );
    23. }
    24.  
    25. private:
    26.  
    27. QList<MyTcpConnection*> _clients;
    28.  
    29. };
    To copy to clipboard, switch view to plain text mode 

    This part seems to work perfectly, but if someone sees something wrong, feel free to say it to me.

    The part that doesn't work well is when a client disconnects. Like the fortuneserver/client example, I connected the connectionClosed() signal to the deleteLater() slot, but I also need to delete the pointer from the _clients list in the MyTcpServer class. To do that, I store a pointer to the MyTcpServer so I can get the clients list and delete the pointer to the MyTcpConnection using QList::removeAll( const T& value ).

    The significant code:
    Qt Code:
    1. class MyTcpConnection : public QTcpSocket
    2. {
    3. Q_OBJECT
    4.  
    5. public:
    6.  
    7. MyTcpConnection( MyTcpServer* parent, int sock )
    8. : QTcpSocket( static_cast<QObject*>( parent ) ),
    9. {
    10. _server = parent;
    11. connect( this, SIGNAL( disconnected() ), SLOT( slotOnDisconnect() ) );
    12. connect( this, SIGNAL( connectionClosed() ), SLOT( deleteLater() ) );
    13. setSocketDescriptor( sock, QAbstractSocket::ConnectedState, QIODevice::ReadWrite );
    14. }
    15.  
    16. private:
    17.  
    18. MyTcpServer* _server;
    19.  
    20. private slots:
    21.  
    22. void slotOnDisconnect()
    23. {
    24. _server->clients().removeAll( this );
    25. }
    26.  
    27. };
    To copy to clipboard, switch view to plain text mode 

    The problem is that removeAll doesn't remove the MyTcpConnection pointer from the _clients list!

    Making the function a bit more verbose, like this:
    Qt Code:
    1. qDebug( "before: %d clients", _server->clients().size() );
    2. int removed = _server->clients().removeAll( this );
    3. qDebug( "%d clients removed", removed );
    4. qDebug( "after: %d clients", _server->clients().size() );
    To copy to clipboard, switch view to plain text mode 


    ...this is what happens:
    before: 2 clients
    1 clients removed
    after: 2 clients

    I thought that maybe removeAll didn't really find and removed the client although it returns 1, so I also tried this:
    Qt Code:
    1. qDebug( "before: %d clients", _server->clients().size() );
    2. for( int i = 0; i < _server->clients().size(); ++i )
    3. {
    4. MyTcpSocket* client = _server->clients().at(i);
    5. if( client == this )
    6. {
    7. qDebug( "FOUND IT: removing..." );
    8. _server->clients().removeAt(i);
    9. break;
    10. }
    11. else qDebug( "this is not the one" );
    12. }
    13. qDebug( "after: %d clients", _server->clients().size() );
    To copy to clipboard, switch view to plain text mode 

    ...but no luck:
    before: 2 clients
    FOUND IT: removing...
    after: 2 clients

    Does anyone know what I'm doing wrong?

    P.S. Sorry for the long explanation, but I explained my problem in another place and I got no answers, so I thought trying again here, with more information. I hope the cross-posting isn't a problem as I didn't get a single answer at the other place.

  2. #2
    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: removeAll not working

    Are you sure removeAll actually gets called? Could you put a qDebug statement inside the slot which does the removal? If removeAll() returns 1, then it did remove the item, maybe (because of some optimisations?) you get an invalid value for size of the list afterwards? Could you, after removal, iterate the list and see what elements it really contains?

  3. #3
    Join Date
    Jul 2006
    Posts
    3
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: removeAll not working

    Thanks for the incredibly quick reply!

    > Are you sure removeAll actually gets called? Could you put a qDebug statement inside the slot which does the removal?

    The qDebug statements I mentioned are actually in the slotOnDisconnect() slot, before and after the removeAll call (I should have made that clearer). So I am pretty sure that removeAll gets called.

    > If removeAll() returns 1, then it did remove the item, maybe (because of some optimisations?) you get an invalid value for size of the list afterwards? Could you, after removal, iterate the list and see what elements it really contains?

    I will do a little test iterating over the list, but I can tell you already that when I connect a client, close it, and then connect again, the client starts receiving all messages twice. Isn't that strange? Shouldn't I get a segfault for the following reason?

    1. I connect a client, a MyTcpSocket object is created and a pointer is stored in the _clients list.
    2. I close the client. The connectionClosed() -> deleteLater() connection deletes the MyTcpSocket, but removeAll doesn't remove the pointer from the _clients list.
    3. I connect the client again, another MyTcpSocket object is created and its pointer stored in the _clients list. Now we have two items in the list, but one is pointing to a deleted object.
    4. When sending a message to the clients a pointer to a deleted object gets used (step 2). Segfault?

    It's as if the first MyTcpSocket never gets deleted and when a new client connects, the same socket is reused. Maybe that's causing the problem?

    Thanks in advance for your interest

  4. #4
    Join Date
    Sep 2007
    Posts
    4
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: removeAll not working

    hello there..im also working with this fuction..
    how can i list all connected client?
    can u give me ur working example

  5. #5
    Join Date
    Dec 2006
    Posts
    9
    Thanked 6 Times in 5 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: removeAll not working

    Hi,

    the problem is that you don't remove the client form the "real" list of clients.

    Your clients method returns a copy of the clients list, your code would only work if you return a reference.

    Changing
    Qt Code:
    1. QList<MyTcpConnection*> MyTcpServer::clients()
    To copy to clipboard, switch view to plain text mode 
    to
    Qt Code:
    1. QList<MyTcpConnection*>& MyTcpServer::clients()
    To copy to clipboard, switch view to plain text mode 
    should do the trick.

Similar Threads

  1. Replies: 1
    Last Post: 11th June 2006, 22:25
  2. Mac OS X UI not working
    By hvengel in forum Qt Programming
    Replies: 3
    Last Post: 1st April 2006, 01:02
  3. Signals/Slots stopped working
    By Jimmy2775 in forum Qt Programming
    Replies: 8
    Last Post: 31st March 2006, 21:11
  4. QT Service and working directory
    By Lele in forum Qt Programming
    Replies: 1
    Last Post: 23rd January 2006, 11:46
  5. QSettings - beginReadArray not working
    By Mike in forum Qt Programming
    Replies: 7
    Last Post: 9th January 2006, 21:24

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.