1

I'm currently facing a strange problem in Qt. I have an application that handles multiple clients using the QTcpSocket. The clients provide the server with login details and the server is doing a check on the MySQL database to verify the credentials on a separate thread.

I have 2 different client programs that log-in to this server 1. A simple client using Qt to connect there 2. A client that is coded in C-Sharp (.net)

However

When the second client tries to log-in to the server, i get an error on the server telling me this:

QObject: Cannot create children for a parent that is in a different thread. Parent is QNativeSocketEngine(0x1231e00), parent's thread is QThread(0xc625f0), current thread is CMySQLHandler(0xc67188)

I'm guessing this is happening on the MySQL handler thread But the weird part is, it is not happening at all on the client that is coded in Qt

here is the code:

void CMySQLHandler::onAuthRequest(ulong clientID, QString email, QString psw, QString HWID, QString ip)
{

    string pass = "", salt = "", name = "", avatar = "";
    uint UserID = 0;
    CUserData *extra = new CUserData();
    bool success = false;
    QString failReason = "Success";

    string Query = "SELECT password, username, avatar, userid FROM jos_users LEFT JOIN jos_community_users ON jos_users.id = jos_community_users.userid WHERE email = '"+email.toStdString()+"'";
    SQLRow Row = GetRow(Query);

    if(!Row.empty())
    {
        QString hashedPass = QString(Row[0].c_str());
        pass = hashedPass.split(':').at(0).toStdString();
        salt = hashedPass.split(':').at(1).toStdString();


        name = Row[1];
        avatar = Row[2];
        UserID = QString(Row[3].c_str()).toUInt();
        QByteArray data;
        data.append((psw + QString(salt.c_str())));
        QString blah = QString(QCryptographicHash::hash(data,QCryptographicHash::Md5).toHex());
        if(QString(pass.c_str()) == blah )
            success = true;
        else
            failReason = "Invalid password";

    }
    else
    {
        failReason = "E-Mail not found";
        emit Handle->onAuthCompleted(clientID, false, failReason, extra);
        return;
    }

    extra->Avatar += avatar.c_str();
    extra->UserID = UserID;

    extra->Username = QString(name.c_str());

    emit Handle->onAuthCompleted(clientID, true, QString(), extra);
}

here's the signal definitions

void CMySQLHandler :: onTimerInit()
{

    //Authentication
    connect(this, SIGNAL(doAuthCompleted(ulong,bool,QString,CUserData*)), Handle, SLOT(onAuthCompleted(ulong,bool,QString,CUserData*)));
    connect(Handle, SIGNAL(doRequestAuth(ulong,QString,QString,QString,QString)), this, SLOT(onAuthRequest(ulong,QString,QString,QString,QString)));
    //end


    CMySQL::Init(Handle);
}

I am new to the Qt framework. Please excuse the lack of knowledge.

Thank you for your time reading this.

NG_
  • 6,895
  • 7
  • 45
  • 67
Stavros Krst
  • 11
  • 1
  • 2

2 Answers2

0

Qt uses an concept of ownership of objects by threads. Thread own objects to do the signal/slot mechanism. The problem is that you are trying to create an new object in Thread CMySQLHandler(0xc67188) and assign it the parent QNativeSocketEngine(0x1231e00). But QNativeSocketEngine is owned by QThread(0xc625f0) which is not allowed. I can't see the error in your code so you may need to do some more debugging to find the line that cause the error and edit your question.

JustMaximumPower
  • 1,257
  • 3
  • 11
  • 22
  • i call this void DoAuth(ulong id, QString email, QString pass, QString hwid, QString ip) { emit doRequestAuth(id, email, pass, hwid, ip); } maybe it is because i call it from a non-qobject object? – Stavros Krst Nov 13 '12 at 14:05
0

This kind of different-thread problems happen all the time with Qt when you use multiple threads. The canonical way to solve this problem is to use signals and slots.

The error doesn't happen in onAuthRequest, it is probably earlier, where you try to call this function. Maybe you are creating a CMySQLHandler object in a one thread, and try to execute member functions of it in another.

If you for some reason need to call a function of a object which belongs to a different threat, create a slot in the object which wraps the function and call it with an emit.

See the similar question QObject: Cannot create children for a parent that is in a different thread

Community
  • 1
  • 1
Gunther Piez
  • 29,760
  • 6
  • 71
  • 103
  • yes but this is working on the QT coded client the only time it is doing this is when i try it with the C-sharp coded client. They both send the same data and undergo the same routine. could it be that the call to 'emit doAuthRequest()' is made from a non-QObject class? – Stavros Krst Nov 13 '12 at 14:29
  • after some debugging i've commented out (Handle->onAuthCompleted(clientID, true, QString(), extra);) and it seems that it is causing this. – Stavros Krst Nov 13 '12 at 14:55