Results 1 to 11 of 11

Thread: QSocketNotifier: socket notifiers cannot be disabled from another thread

  1. #1
    Join Date
    Mar 2007
    Posts
    5
    Qt products
    Qt4

    Default QSocketNotifier: socket notifiers cannot be disabled from another thread

    I have a code like this

    void Client::run()
    {

    tcpSocket = new QTcpSocket();

    if (tcpSocket->setSocketDescriptor(socketDesc))
    {

    peerAdress = tcpSocket->peerAddress().toString();
    peerPort = tcpSocket->peerPort();

    emit connected();
    }

    while (!quit)
    {
    if (tcpSocket->waitForReadyRead(Timeout))
    {
    // Read data
    QDataStream in(tcpSocket);
    in.setVersion(QDataStream::Qt_4_0);
    in >> buffer;
    qDebug() << buffer<<endl;
    }


    }
    //slot to send a message
    void Client::sendMessage(QString message)
    {
    tcpSocket->write(message);
    }


    I have also sender thread gets message from message queues and send signal to thread above to write message socket.

    it is implemented as below.

    void Sender::run()
    {

    while(!quit)
    {
    qDebug() <<"sending message" <<endl;
    emit sendMessage("message");

    sleep(1);
    }
    }

    but when code runs I get following error.

    what is the problem.


    QObject: Cannot create children for a parent that is in a different thread.
    and
    QSocketNotifier: socket notifiers cannot be disabled from another thread

  2. #2
    Join Date
    Aug 2006
    Location
    Switzerland
    Posts
    52
    Thanked 13 Times in 11 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QSocketNotifier: socket notifiers cannot be disabled from another thread

    Quote Originally Posted by dabiabilus View Post
    I have a code like this
    If it is a code, why don't you use [code] tag?

    Quote Originally Posted by dabiabilus View Post
    Qt Code:
    1. void Client::run()
    2. {
    3. tcpSocket = new QTcpSocket();
    To copy to clipboard, switch view to plain text mode 
    I assume that Client class is derived from QThread class.Parent object (Client) was probably created in the main thread. Everything that is done in its run() method is executed in another thread. So child object (QTcpSocket) is created in different thread than its parent lives. This is not allowed and that's why you get error:
    Quote Originally Posted by dabiabilus View Post
    QObject: Cannot create children for a parent that is in a different thread.
    Quote Originally Posted by dabiabilus View Post
    QSocketNotifier: socket notifiers cannot be disabled from another thread
    Hm... I'll be guessing here. Your client thread doesn't have an event loop (you're not calling exec() method anywhere in run()). You are waiting for readyRead in client thread, so in fact you are waiting for some signal from QTcpSocket. But it's impossible to receive it in client thread cause it has no event loop.
    The Wheel weaves as the Wheel wills.

  3. The following user says thank you to danadam for this useful post:

    milli (20th May 2011)

  4. #3
    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: QSocketNotifier: socket notifiers cannot be disabled from another thread

    What is buffer? Where has it been created?
    J-P Nurmi

  5. #4
    Join Date
    Mar 2007
    Posts
    5
    Qt products
    Qt4

    Default Re: QSocketNotifier: socket notifiers cannot be disabled from another thread

    Quote Originally Posted by danadam View Post
    If it is a code, why don't you use [code] tag?


    I assume that Client class is derived from QThread class.Parent object (Client) was probably created in the main thread. Everything that is done in its run() method is executed in another thread. So child object (QTcpSocket) is created in different thread than its parent lives. This is not allowed and that's why you get error:

    yes that is true , but where should I create QTcpSocket, in the constructor of the Client or elsewhere. Also in QT documentation it is stated that

    "The child of a QObject must always be created in the thread where the parent was created. This implies, among other things, that you should never pass the QThread object (this) as the parent of an object created in the thread (since the QThread object itself was created in another thread).
    "
    is this means that child of a QObject(tcpSocket) should be created in the main thread. Or do not passing "this"(Client) into constructor of the tcpSocket in the run method will be sufficent


    Hm... I'll be guessing here. Your client thread doesn't have an event loop (you're not calling exec() method anywhere in run()). You are waiting for readyRead in client thread, so in fact you are waiting for some signal from QTcpSocket. But it's impossible to receive it in client thread cause it has no event loop.

    Why do I need an evet loop. tcpSocket can signal events such as "connected","disconnected" ,"errors". I do not need to call exec. I will try it.
    Problem occurs when Client receives "sendMessage" signal of the sender, and tries to write socket.

  6. #5
    Join Date
    Aug 2006
    Location
    Switzerland
    Posts
    52
    Thanked 13 Times in 11 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QSocketNotifier: socket notifiers cannot be disabled from another thread

    Quote Originally Posted by dabiabilus View Post
    Why do I need an evet loop. tcpSocket can signal events such as "connected","disconnected" ,"errors". I do not need to call exec. I will try it.
    My mistake here, event loop isn't required. But I'm not sure if you are aware that in such case your sendMessage slot isn't executed in client thread. There are three threads here: main thread, client thread and sender thread. Socket reading is done in client thread, that's obvious. But sendMessage slot is executed either in main thread (if you make queued connection between Sender and Client) or in sender thread (if you make direct connection between Sender and Client).
    Quote Originally Posted by dabiabilus View Post
    Problem occurs when Client receives "sendMessage" signal of the sender, and tries to write socket.
    I wrote a program like yours (two threads, Client and Sender) and I don't have that problem. Of course "QObject: Cannot create children for a parent that is in a different thread." is still there, but I wasn't able to reproduce "QSocketNotifier: socket notifiers cannot be disabled from another thread"
    Last edited by danadam; 19th March 2007 at 22:38.
    The Wheel weaves as the Wheel wills.

  7. #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: QSocketNotifier: socket notifiers cannot be disabled from another thread

    Quote Originally Posted by danadam View Post
    My mistake here, event loop isn't required.
    On the contrary, it is required to make the queued connections work.

    Quote Originally Posted by danadam View Post
    sendMessage slot is executed either in main thread (if you make queued connection between Sender and Client) or in sender thread (if you make direct connection between Sender and Client).
    Most likely it's executed in the Sender thread. QThread objects live in the thread that has created them, so most likely both Sender and Client objects live in the main thread, while the socket lives in the Client thread.

    Since both Sender and Client live in the same thread, most likely a direct connection was made between them, whereas it should be a queued connection. When making connections between thread object, it's safer to explicitly specify the connection type.

  8. #7
    Join Date
    Aug 2006
    Location
    Switzerland
    Posts
    52
    Thanked 13 Times in 11 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QSocketNotifier: socket notifiers cannot be disabled from another thread

    To make things clear, here is output from my test program (three threads: main, client, sender, neither client nor sender has event loop, client and sender live in main thread, socket lives in client thread):

    Qt::AutoConnection (slot is executed in main thread):
    Qt Code:
    1. "main, thread: b70a28e0"
    2. server is listening
    3. incoming connection
    4. "client started, thread: b6e82bb0"
    5. "sender started, thread: b6681bb0"
    6. "sender emit signal, thread: b6681bb0"
    7. "client slot, thread: b70a28e0"
    8. QObject: Cannot create children for a parent that is in a different thread.
    9. "sender emit signal, thread: b6681bb0"
    10. "client slot, thread: b70a28e0"
    To copy to clipboard, switch view to plain text mode 

    Qt::DirectConnection (slot is executed in sender thread):
    Qt Code:
    1. "main, thread: b71698e0"
    2. server is listening
    3. incoming connection
    4. "client started, thread: b6f49bb0"
    5. "sender started, thread: b6748bb0"
    6. "sender emit signal, thread: b6748bb0"
    7. "client slot, thread: b6748bb0"
    8. QObject: Cannot create children for a parent that is in a different thread.
    9. "sender emit signal, thread: b6748bb0"
    10. "client slot, thread: b6748bb0"
    To copy to clipboard, switch view to plain text mode 

    Qt::QueuedConnection (slot is executed in main thread):
    Qt Code:
    1. "main, thread: b70df8e0"
    2. server is listening
    3. incoming connection
    4. "client started, thread: b6ebfbb0"
    5. "sender started, thread: b66bebb0"
    6. "sender emit signal, thread: b66bebb0"
    7. "client slot, thread: b70df8e0"
    8. QObject: Cannot create children for a parent that is in a different thread.
    9. "sender emit signal, thread: b66bebb0"
    10. "client slot, thread: b70df8e0"
    To copy to clipboard, switch view to plain text mode 
    The Wheel weaves as the Wheel wills.

  9. #8
    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: QSocketNotifier: socket notifiers cannot be disabled from another thread

    Quote Originally Posted by danadam View Post
    Qt::AutoConnection (slot is executed in main thread):
    That's quite interesting. The docs say:
    If the signal is emitted from the thread in which the receiving object lives, the slot is invoked directly, as with Qt::DirectConnection; otherwise the signal is queued, as with Qt::QueuedConnection.
    So it looks like that if you use Qt::AutoConnection, the effective connection type is established for each signal, not once when the connection is created.

    Quote Originally Posted by danadam View Post
    Qt::QueuedConnection (slot is executed in main thread):
    It looks like the Client object lives in the main thread, so the meta call events go through main thread's event queue. One possible solution is to use QObject::moveToThread() (of course in such case there must be an event loop running in the Client thread).

  10. #9
    Join Date
    Mar 2007
    Posts
    5
    Qt products
    Qt4

    Default Re: QSocketNotifier: socket notifiers cannot be disabled from another thread

    Quote Originally Posted by jacek View Post
    That's quite interesting. The docs say:
    So it looks like that if you use Qt::AutoConnection, the effective connection type is established for each signal, not once when the connection is created.


    It looks like the Client object lives in the main thread, so the meta call events go through main thread's event queue. One possible solution is to use QObject::moveToThread() (of course in such case there must be an event loop running in the Client thread).


    I solve the problem as below, but there is other things to solve.

    Sender thread lives in main thread.
    Client lives main thread.
    Socket lives in Client thread.

    As you have said , with direct connection between sender and client ,Client slot is invoked in sender thread. That is why, slot can not write to socket due to fact that socket lives in Client thread.

    With queued connection between sender and client , slot of Client is invoked in main thread because client lives in main thread. That is why, client slot can not write socket due to fact that socket lives in Client thread not in main thread.

    To solve the problem, I have created new class that is responsible for initialization of the socket. This class also have slot that writes to the socket. I have created this class in the run block of the Client class. And connect to signal of the sender with slot of this class. it worked correctly using queud connection but as you said I needed "exec" call to be able use queued connection.

    But when I call "exec" it blocks in the run block. I can not do anything inside. for example I can not use blocking approach as follows.
    Qt Code:
    1. while (!quit)
    2. {
    3.  
    4. if (tcpSocket->waitForReadyRead(Timeout))
    5. {
    6. // Read data
    7. QDataStream in(tcpSocket);
    8. in.setVersion(QDataStream::Qt_4_0);
    9. in >> buffer;
    10. qDebug() << buffer<<endl;
    11.  
    12. }
    13. }
    To copy to clipboard, switch view to plain text mode 

    because I have to read and write same socket in my design I have to alternative

    1 -) Do not use blocking approach. Use simply signal / slot way. but as I know signals are slow . my application time critical. should handle lots of messages.I can not choose this approach.

    2-) use blocking approach but create separe sockets for writing and reading.

    3-) Use an other socket library

    am I right ?

  11. #10
    Join Date
    Aug 2006
    Location
    Switzerland
    Posts
    52
    Thanked 13 Times in 11 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QSocketNotifier: socket notifiers cannot be disabled from another thread

    Quote Originally Posted by dabiabilus View Post
    As you have said , with direct connection between sender and client ,Client slot is invoked in sender thread. That is why, slot can not write to socket due to fact that socket lives in Client thread.

    With queued connection between sender and client , slot of Client is invoked in main thread because client lives in main thread. That is why, client slot can not write socket due to fact that socket lives in Client thread not in main thread.
    To say the truth I don't know why you can't write to socket in different thread. My previous guessing was only... er... guessing. I checked that and it appears that there is no problem with writing to socket in sender thread or main thread. Client slot in the above examples did it and it wasn't complaining.
    The Wheel weaves as the Wheel wills.

  12. #11
    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: QSocketNotifier: socket notifiers cannot be disabled from another thread

    Quote Originally Posted by dabiabilus View Post
    1 -) Do not use blocking approach. Use simply signal / slot way. but as I know signals are slow
    What exactly is slow in signals?

    Quote Originally Posted by dabiabilus View Post
    am I right ?
    There is also a 4th solution: you can use a non-blocking approach without using signals and slots.

Similar Threads

  1. question about socket and threads?
    By oob2 in forum Qt Programming
    Replies: 2
    Last Post: 27th February 2007, 12:42
  2. Problem closing a QMainWindow in Qt4.2
    By ian in forum Qt Programming
    Replies: 11
    Last Post: 17th October 2006, 01:49
  3. How to write on a socket in another thread?
    By Valheru in forum Qt Programming
    Replies: 7
    Last Post: 12th October 2006, 11:52

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.