qthread - Qt Threading code different behavior in MAC,Linux and Windows -


i have written code server accepts connections different clients. each client serviced in different threads. each thread accesses database data , updates data clients connected server.

1) first time when ui asks data server, responds properly, after server not read socket i.e. server's readyread() doesn't invoked. funnily enough, works fine in mac , linux, issue seen on windows

2) able verify when db module emits signal caught threads, hang occurs, because worked fine when removed emit.

here, attaching needed .h , .cpp codes

defn.h

#ifndef defn_h #define defn_h  struct presetdata{     qstring id;     qstring name;     qstring value;     qstring source; };   #endif // defn_h 

main.cpp

#include <qcoreapplication> #include "myserver.h" #include "mydb.h"  int main(int argc, char *argv[]) {     qcoreapplication a(argc, argv);      mydb db;     myserver server(&db);     server.startserver();      return a.exec(); } 

mydb.h

#ifndef mydb_h #define mydb_h  #include <qobject> #include <qtsql>  #include "defn.h"  class mydb : public qobject {     q_object   public:     explicit mydb(qobject *parent = 0);    signals:     void dataavailable(qstring id, qstring name, qstring value, qstring source);    public slots:     void onupdatedata(qstring id, qstring name, qstring value, qstring source);     void ongetdata(qstring id, qstring name, qstring value, qstring source);    private:     qsqldatabase m_db; };  #endif // mydb_h 

mydb.cpp

#include "mydb.h"  mydb::mydb(qobject *parent) : qobject(parent) {     m_db = qsqldatabase::adddatabase("qsqlite");     m_db.setconnectoptions();     m_db.setdatabasename("d:/mysimulator/new folder/tcpserver1/db.db");      if (m_db.open()){        qdebug() << "db opened succesfully" ;     }else{        qdebug() << "db opening failed" ;     }      qstringlist tables = m_db.tables();     if (tables.contains("presets", qt::caseinsensitive)){          qdebug() << "db contains data" ;          return;     } }  void mydb::ongetdata(qstring id, qstring name, qstring value, qstring source) {     qdebug() << "ongetdata" ;     qstring querystring = "select value 'presets' id = \'" + id + "\'";     qsqlquery q;      bool result = q.exec(querystring);      if (result){        if (q.next()){          value = q.value(q.record().indexof("value")).tostring();          qdebug() << " retrieved value = " << value ;          emit dataavailable(id, name, value, source);        }else{          qdebug("empty result");        }    }else{       qdebug("no result");    } }  void mydb::onupdatedata(qstring id, qstring name, qstring value, qstring source) {     qdebug() << "onupdatedata" ;     qstring querystring = "update 'presets' set value = \'" + value + "'\ id = \'" + id + "\'";     qsqlquery q;      qsqldatabase::database().transaction();     bool result = q.exec(querystring);      if (result){        qsqldatabase::database().commit();        ongetdata(id, name, "", "000");     }else{         qdebug("no result");     } } 

mythread.h

#ifndef mythread_h #define mythread_h  #include <qthread> #include <qtcpsocket> #include <qabstractsocket> #include <qdebug> #include "defn.h" #include "mydb.h"  class mythread : public qthread {      q_object    public:      explicit mythread(int id, mydb* db, qobject * parent = 0);       void run();      void parseinput(qstring string);     signals:      void error(qtcpsocket::socketerror socketerror);      void updatedata(qstring id, qstring name, qstring value, qstring source);      void getdata(qstring id, qstring name, qstring value, qstring source);     public slots:      void readyread();      void disconnected();      void ondataavailable(qstring id, qstring name, qstring value, qstring source);     private:      qtcpsocket* socket;      int socketdescriptor;      mydb* db; };  #endif // mythread_h 

mythread.cpp

#include "mythread.h" #include "qtcpserver.h" #include "qabstractsocket.h"  mythread::mythread(int id, mydb* db, qobject * parent ):    qthread(parent) {     this->socketdescriptor = id ;     this->db = db; }  void mythread::run() {     // thread starts here.     qdebug() << socketdescriptor << "starting thread" ;     socket = new qtcpsocket();     if (!socket->setsocketdescriptor(this->socketdescriptor)){         emit error(socket->error());         return;     }      connect(socket, signal(readyread()), this, slot(readyread()), qt::directconnection);     connect(socket, signal(disconnected()), this, slot(disconnected()), qt::directconnection);     connect(this, signal(getdata(qstring, qstring , qstring , qstring )), this->db, slot(ongetdata(qstring , qstring , qstring , qstring )));     connect(this, signal(updatedata(qstring , qstring , qstring , qstring )), this->db, slot(onupdatedata(qstring , qstring , qstring , qstring )));     connect(this->db, signal(dataavailable(qstring , qstring , qstring , qstring )), this, slot(ondataavailable(qstring , qstring , qstring , qstring )));      qdebug() << socketdescriptor << "client connected" ;      exec(); }  void mythread::readyread() {     qbytearray data = socket->readall();     qdebug() << socketdescriptor << "data in: " << data;     parseinput(data); }  void mythread::disconnected() {     qdebug() << socketdescriptor << "disconnected" ;     socket->deletelater();     exit(0); }  void mythread::parseinput(qstring datafromtcp) {     qdebug() << socketdescriptor << ":" <<"parseinput  "  << datafromtcp;      if (datafromtcp.isempty())        return;      qstringlist list1 = datafromtcp.split("\n", qstring::skipemptyparts);      qdebug() << socketdescriptor << ":" << "list1 begin";     (int = 0 ; < list1.count(); i++)     {         qdebug() << i<< ":" << list1.at(i);     }     qdebug() << socketdescriptor << ":" << "list1 end";      if (list1.count() < 1){          return;     }      qstring strmessage = "";     (int = 0 ; < list1.count() ; i++)     {         strmessage = list1[i];         qstringlist list2 = strmessage.split(" ", qstring::skipemptyparts);          qdebug() << socketdescriptor << ":" << "list2 begin";         (int = 0 ; < list2.count(); i++)         {             qdebug() << i<< ":" << list2.at(i);         }          qdebug() << socketdescriptor << ":" << "list2 end";          if (list2.count() < 1){             break;         }          qstring id = list2[1];         qstring source = qstring::number(socketdescriptor) ;         if (list2[0] == "get"){            emit getdata(id, "", "", source);         }          else if (list2[0] == "upd"){             qstring value = list2[2];             emit updatedata(id, "", value, source);         }     } }  void mythread::ondataavailable(qstring id, qstring name, qstring value, qstring source) {     if( (qstring::number(socketdescriptor) == source) || ("000" == source ) ) {        qdebug() << socketdescriptor << " : on data available " << id << name << value ;        qstring data = "data " + id + " " + value + " " + "\n" ;        qbytearray ba;        ba.append(data);        socket->write(ba);     } } 

myserver.h

#ifndef myserver_h #define myserver_h  #include <qdebug> #include <qobject> #include <qtcpserver> #include <qtcpsocket>  #include "mythread.h" #include "mydb.h"  class myserver: public qtcpserver {       q_object    public:       explicit myserver(mydb* pdb, qobject* parent = 0);       void startserver();     signals:     public slots:     protected:       void incomingconnection(qintptr socketdescriptor);     private:       mydb* pdb ; };  #endif // myserver_h 

myserver.cpp

#include "myserver.h"  myserver::myserver(mydb* pdb, qobject* parent ):    qtcpserver(parent) {     this->pdb = pdb; }  void myserver::startserver() {     if (!this->listen(qhostaddress::any, 1234)){         qdebug() << "could not start server " << this->errorstring();     }     else{         qdebug() << " server running... ";     } }  void myserver::incomingconnection(qintptr socketdescriptor) {     qdebug() << socketdescriptor << " connecting... ";     mythread *thread = new mythread(socketdescriptor, pdb, this);      connect(thread, signal(finished()), thread, slot(deletelater()));      thread->start(); } 

here signal mentioned above dataavailable "mydb.cpp". if comment out line server responds client messages. if signal emitted after initial response, server seems hang , no longer reacts incoming messages client. same code working fine in mac , linux. having problem in windows only. let me know doing wrong failing in windows? in advance helping me out.

edit:

the objective of code whenever thread causes update call database, every thread including 1 called update gets informed change. expected other thread runs @ time receives signal.

this expected of server:

  1. be able allow tcp connections multiple clients simultaneously.

  2. if client requests info, gets required data on tcp connection.

  3. if client updates info, clients including updating client, gets notifications on tcp connection.

well, starters, code not thread-safe. create single instance of mydb in main() function, call threads without protecting data member. also, signals emitted, updating data without protection. if 2 threads happen running @ same time?

secondly, , more important: whenever emit dataavailable() call functions in other thread objects in own thread. code path when data arrives:

  1. mythread::parseinput() emits
  2. mythread::getdata(), connected to
  3. mydb::ongetdata(), emits
  4. mydb::dataavailable, connected (drumroll....)
  5. mythread::ondataavailable, calls
  6. socket->write()

so if data arrives in thread #1, you're going send data mythread object #2, #3, #4, etc .... thread #1. depending on os, bad news. don't know enough windows threads know code terminally broken.

if want update database , relay data can dispense threads , use sequential program handles sockets using regular qt signals , slots fine.


Comments

Popular posts from this blog

javascript - Jquery show_hide, what to add in order to make the page scroll to the bottom of the hidden field once button is clicked -

javascript - Highcharts multi-color line -

javascript - Enter key does not work in search box -