Results 1 to 2 of 2

Thread: QThread quit() issue.

  1. #1
    Join Date
    Oct 2009
    Posts
    9
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Question QThread quit() issue.

    Hi All,

    I am trying to use Curl and QThread to make asynchronous calls. So I have created my own HTTP Handler class in which I perform curl requests using QTimer in separate threads. Now, all instances of below class are being called from a singleton class which is non-gui and its methods will be called from GUI thread. I have 3 instances of Handler.

    Strangely, the code works fine on every Windows machine and also MAC, except for WIN7 64 bit where it crashes.

    The crash exception code is c00005. 1st instance runs successfully, and then 2nd instance starts and after its 1st requestFinished signal I do a handle->finish, in which I call quit(), (now changed it to exit(0) ) which crashes the application.

    Can anyone please tell me where possibly a crash can happen during quit() and how to go about debugging ?

    The thread code is pasted below;

    Subclassed QThread and code is below:

    HTTPHANDLER.h

    #include <QThread>

    #include <QByteArray>

    #include <QMutex>

    #include <QMap>

    class HttpHandler : public QThread

    {

    Q_OBJECT

    friend size_t gHttpHandlerCurlDataAvailableCallback(void *ptr, size_t size, size_t nmemb, void *stream);

    public:

    HttpHandler();

    ~HttpHandler();

    bool setRequest(QString url, QByteArray postData, QMap<QString,QString> headerList);

    void execute();

    void finish();

    void userAgentUse( QString &userAgent );

    signals:

    void requestFinished(int curl_code, QByteArray response);

    protected:

    virtual void run();

    protected slots:

    void perform();

    private:

    size_t curlDataReceived(void *ptr, size_t size, size_t nmemb);

    bool m_requestPending;

    QMutex m_mutex;

    QMutex m_mutex1;

    QString m_url;

    QByteArray m_respData;

    QByteArray m_reqData;

    QMap<QString, QString> m_reqHeaders;

    QThread *prevThread;

    };


    HTTPHANDLER.cpp


    #include "httphandler.h"

    #include <QTimer>

    #include "curl.h"

    #include <storageengine.h>

    #include <Log.h>

    size_t gCurlVerboseCallBack(CURL *handle, curl_infotype type, char *data, size_t size, void *userp)

    {

    QByteArray ba;

    ba.append(data, size);

    QString str(ba);

    return 0;

    }

    size_t gHttpHandlerCurlDataAvailableCallback(void *ptr, size_t size, size_t nmemb, void *stream)

    {

    HttpHandler *handler = (HttpHandler *)stream;

    return handler->curlDataReceived(ptr, size, nmemb);

    }

    HttpHandler::HttpHandler()

    : m_requestPending(false)

    {

    }

    HttpHandler::~HttpHandler()

    {

    if (isRunning())

    {

    QMutexLocker lock( &m_mutex );

    terminate();

    wait();

    }
    }

    bool HttpHandler::setRequest(QString url, QByteArray postData, QMap<QString,QString> headerList)

    {

    QMutexLocker lock(&m_mutex);

    if (m_requestPending)

    {

    return false;

    }

    //accept request

    m_url = url;

    m_reqData = postData;

    m_reqHeaders = headerList;

    m_respData.clear();

    m_requestPending = true;

    return true;

    }

    void HttpHandler::execute()

    {

    if( isRunning() )

    {

    terminate();

    wait();

    }
    prevThread = this->thread();

    QObject::moveToThread( this );

    start();

    }

    void HttpHandler::run()

    {
    QTimer::singleShot(0, this, SLOT(perform()));

    exec();

    }

    void HttpHandler::finish()

    {

    DimdimLogger::getInstance()->write("HttpHandler Finished\n");

    QMutexLocker lock(&m_mutex);

    m_requestPending = false;

    exit(0);

    moveToThread( prevThread );
    }

    void HttpHandler::userAgentUse( QString &userAgent )

    {

    QMutexLocker lock(&m_mutex);

    #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)

    userAgent = "API/5.5/windows";

    #elif defined(linux) || defined(__linux) || defined(__linux__) || defined(__GNU__) || defined(__GLIBC__)

    userAgent = "API/5.5/linux";

    #elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)

    #if !defined(MAC_OS_X_VERSION_10_6)

    userAgent = "API/5.5/snow_leopard";

    #else

    userAgent = "API/5.5/leopard";

    #endif

    #elif defined(unix) || defined(__unix) || defined(_XOPEN_SOURCE) || defined(_POSIX_SOURCE)

    userAgent = "API/5.5/unix";

    #endif

    }

    void HttpHandler:erform()

    {

    char * cv = curl_version();

    CURL * curl_handle = curl_easy_init();

    // curl_easy_setopt(curl_handle, CURLOPT_TCP_NODELAY, 1);

    // curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1);

    // curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, -1);

    QString userAgent;

    userAgentUse( userAgent );

    curl_easy_setopt( curl_handle, CURLOPT_USERAGENT, userAgent.toStdString().c_str() );

    // curl_easy_setopt(curl_handle, CURLOPT_DEBUGDATA, this);

    // curl_easy_setopt(curl_handle, CURLOPT_DEBUGFUNCTION, gCurlVerboseCallBack);

    // curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L);

    m_url.toStdString().c_str());

    //set proxy info

    QString proxyAddress, socksVersion, domain, p_userName, p_password, auth, autodetect;

    StorageEngine::getInstance()->readProxyInfo1( proxyAddress, socksVersion, domain, p_userName, p_password, autodetect );

    //set proxy info

    if( ( socksVersion.compare("3") != 0) && //not direct connection

    ( socksVersion.compare("4") != 0) ) //bypass not selected by user

    {

    curl_easy_setopt( curl_handle, CURLOPT_PROXY,

    proxyAddress.toAscii().data());

    //curl_easy_setopt( curl_handle, CURLOPT_USERPWD, "");

    if( !domain.isEmpty() )

    {

    auth.append( domain );

    if( !p_userName.isEmpty() )

    {

    auth.append( "/" + p_userName );

    if( !p_password.isEmpty() )

    {

    auth.append( ":" + p_password );

    }

    }

    }

    curl_easy_setopt( curl_handle, CURLOPT_PROXYUSERPWD, auth.toStdString().c_str() );

    if( socksVersion.compare( "1" ) == 0 )

    {

    curl_easy_setopt(curl_handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4 );

    }

    else if( socksVersion.compare( "2" ) == 0 )

    {

    curl_easy_setopt(curl_handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5 );

    }

    else

    {

    curl_easy_setopt(curl_handle, CURLOPT_HTTPPROXYTUNNEL, 1);

    curl_easy_setopt(curl_handle, CURLOPT_PROXYAUTH, CURLAUTH_ANY);

    }

    }

    m_url.toAscii().data());

    //set POST fields

    //curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDSIZE, m_reqData.length() );

    if( m_reqData.isEmpty() )

    {

    curl_easy_setopt( curl_handle, CURLOPT_HTTPGET, 1 );

    }

    else

    {

    curl_easy_setopt(curl_handle, CURLOPT_POST, 1);

    curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, m_reqData.data());

    }

    //set the CURL callbacks

    curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, gHttpHandlerCurlDataAvailableCallback);

    curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, this);

    //set headers

    struct curl_slist *headerlist=NULL;

    if (m_reqHeaders.size() > 0)

    {

    QMap<QString,QString>::iterator iter = m_reqHeaders.begin();

    for (;iter != m_reqHeaders.end(); ++iter)

    {

    QString field;

    field = iter.key() + ": " + iter.value();

    headerlist = curl_slist_append(headerlist, field.toAscii().data());

    }

    }

    DimdimLogger::getInstance()->write("HttpHandler: URL is: %s\n", m_url.toAscii().data());

    CURLcode curl_error = curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headerlist);

    if (CURLE_OK != curl_error)

    {

    emit requestFinished((int) curl_error, m_respData);

    curl_slist_free_all(headerlist);

    curl_easy_cleanup(curl_handle);

    return;

    }

    char *url = strdup( m_url.toStdString().c_str() );

    curl_easy_setopt(curl_handle, CURLOPT_URL, url);

    m_url.toAscii().data());

    curl_error = curl_easy_perform(curl_handle);

    m_url.toAscii().data());


    if (headerlist)

    curl_slist_free_all(headerlist);

    curl_easy_cleanup(curl_handle);

    curl_handle = NULL;

    free( url );
    emit requestFinished((int)curl_error, m_respData);

    }

    size_t HttpHandler::curlDataReceived(void *ptr, size_t size, size_t nmemb)

    {

    QMutexLocker lock(&m_mutex);

    QByteArray ba;

    ba.append((const char *)ptr, size * nmemb);

    QString str(ba);

    m_respData.append((const char *)ptr, size * nmemb);

    return size * nmemb;

    }

  2. #2
    Join Date
    Jan 2008
    Location
    Poland
    Posts
    687
    Thanks
    4
    Thanked 140 Times in 132 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: QThread quit() issue.

    I don't think that anyone is going to read this... Use the CODE tags and paste only important part of code.
    I would like to be a "Guru"

    Useful hints (try them before asking):
    1. Use Qt Assistant
    2. Search the forum

    If you haven't found solution yet then create new topic with smart question.

Similar Threads

  1. QTcpSocket as class member of QThread Issue
    By zyangxue in forum Qt Programming
    Replies: 4
    Last Post: 12th December 2009, 06:42
  2. QThread and QTcpSocket
    By ^NyAw^ in forum Qt Programming
    Replies: 3
    Last Post: 12th May 2008, 13:06
  3. QThread exec proplem to stop...
    By patrik08 in forum Qt Programming
    Replies: 29
    Last Post: 21st May 2007, 07:51
  4. Qthread Issue?
    By vishal.chauhan in forum Newbie
    Replies: 3
    Last Post: 29th March 2007, 08:50
  5. Is it possible to create a QThread without inheriting ?
    By probine in forum Qt Programming
    Replies: 6
    Last Post: 23rd March 2006, 22:51

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.