QNetworkAccessManager QMultiPartData post upload a file causing my application to crash..



  • based on the documentation on QHttpMultiPart

    @ QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);

    QHttpPart textPart;
    textPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name="text""));
    textPart.setBody("my text");

    QHttpPart imagePart;
    imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg"));
    imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name="image""));
    QFile *file = new QFile("image.jpg");
    file->open(QIODevice::ReadOnly);
    imagePart.setBodyDevice(file);
    file->setParent(multiPart); // we cannot delete the file now, so delete it with the multiPart

    multiPart->append(textPart);
    multiPart->append(imagePart);

    QUrl url("http://my.server.tld");
    QNetworkRequest request(url);

    QNetworkAccessManager manager;
    QNetworkReply *reply = manager.post(request, multiPart);
    multiPart->setParent(reply); // delete the multiPart with the reply
    // here connect signals etc.@

    You can upload files to any web server using QNetworkAccessManager, thus I made a small client to synchronize files from some of our distant computers to our web server the issue is that the client crashes sometimes in the middle of a transfer, the client never crashes when debugging on my machine. ( The worst thing that can happen to a developper right :? )

    Here is my code sample.

    @
    QFile * io = new QFile(m_configuration.getPathToPos() + "/" + m_pendingTransfers[0].getFileName());
    emit log("trying to open file for transfer..");
    if( !io->open(QIODevice::ReadOnly) )
    {
    // failed to open delete it.
    io->deleteLater();

        // we could not open file let's try again..
        emit log("failed to open " + m_pendingTransfers[0].getFileName() + " for upload");
    
        // emit next pending transfer.
        emit startNextPendingTransfer();
    
        // stop code.
        return;
    }
    
    
    // increment the number of tries.
    m_pendingTransfers[0].incrementAttemps();
    emit log("trying to transfer: " + m_pendingTransfers[0].getFileName() + " attempt " + QString::number(m_pendingTransfers[0].getAttemps()) + "/3");
    
    
    // request.
    QNetworkRequest request(QUrl(m_configuration.getHttpServer() + "/client/polling"));
    request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork);
    
    // multipart.
    QHttpMultiPart * multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
    
    // clientid
    QHttpPart clientIdPart;
    clientIdPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"clientId\""));
    clientIdPart.setBody(QString::number(m_configuration.getClientId()).toUtf8());
    multiPart->append(clientIdPart);
    
    // type of file.
    QHttpPart relativeDestination;
    relativeDestination.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"subPath\""));
    relativeDestination.setBody(m_pendingTransfers[0].getSubPath().toUtf8());
    multiPart->append(relativeDestination);
    
    // file we are uploading.
    QHttpPart filePart;
    filePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"pollingFile\"; filename=\"" + m_pendingTransfers[0].getFileName() + "\""));
    filePart.setBodyDevice(io);
    multiPart->append(filePart);
    
    // set current request.
    m_currentRequest = r_uploadFile;
    
    // create reply.
    emit log("sending file to be uploaded");
    
    // create reply.
    m_reply = m_networkManager.post(request, multiPart);
    
    // update parents for later free'ing.
    multiPart->setParent(m_reply);
    io->setParent(m_reply);
    
    // connect signals & slots.
    connect(m_reply.data(), SIGNAL(finished()), this, SLOT(onHttpFinished()));
    connect(m_reply.data(), SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onHttpError(QNetworkReply::NetworkError)));
    connect(m_reply.data(), SIGNAL(uploadProgress(qint64,qint64)), this, SLOT(onUploadProgress(qint64,qint64)));@
    

    Now this works perfect for 30 - 35 minutes and how of no where the client just crashes in the middle of a transfer, Figured this out by using the signal:
    @
    connect(m_reply.data(), SIGNAL(uploadProgress(qint64,qint64)), this, SLOT(onUploadProgress(qint64,qint64)));
    void CWebboClient::onUploadProgress(qint64 bytesSent, qint64 bytesTotal)
    {
    emit log(QString("upload progress: %1/%2").arg(bytesSent).arg(bytesTotal));
    }
    @

    So now what I am wondering could that be related to the bug entry:
    https://bugreports.qt-project.org/browse/QTBUG-24738

    if it is what can I do untill 4.8.3 is released if not what am I doing wrong :'[

    Thanks in advance.



  • Hi!

    Can you give us backtrace of your application's behaviour crash?



  • [quote author="tucnak" date="1346230277"]Hi!

    Can you give us backtrace of your application's behaviour crash?[/quote]

    hm it never crashes when I debug only on beta machines running without debuggers.
    I might misunderstand but is there a way to get the backtrace of that?



  • [quote author="dsylebee" date="1346243684"]
    [quote author="tucnak" date="1346230277"]Hi!

    Can you give us backtrace of your application's behaviour crash?[/quote]

    hm it never crashes when I debug only on beta machines running without debuggers.
    I might misunderstand but is there a way to get the backtrace of that?[/quote]

    You can get backtrace after debugging or from .core file that Linux generates.



  • [quote author="tucnak" date="1346243887"][quote author="dsylebee" date="1346243684"]
    [quote author="tucnak" date="1346230277"]Hi!

    Can you give us backtrace of your application's behaviour crash?[/quote]

    hm it never crashes when I debug only on beta machines running without debuggers.
    I might misunderstand but is there a way to get the backtrace of that?[/quote]

    You can get backtrace after debugging or from .core file that Linux generates.[/quote]

    Sadly it's on windows, Like I said though the issue never happens in debugging but more likely after running for 3 hours in release mode on a machine without a debugger.



  • I arrives at this post while searching for a problem I was having with QHttpMultiPart not working. It simply was not making the post and never calling any of the signal handlers. I have since figured out the problem, and wanted to drop some breadcrumbs here for anyone else who is in a similar situation.

    The code snipped in the 4.8 QT manual will not work if cut and paste into a method. It mentions connecting the signals to your slots at the end as if the author of the snippet intended for it to be used in an event driven app, but they declared a local QNetworkAccessManager that will fall out of scope if a method returns and it will never complete the post. They even reparented the file and the multipart objects as if it was a snippet ready to be pasted into a method.

    It took me forever to find this problem because those things were misleading. Indeed, the QNetworkAccessManager should be allocated dynamically and parented to your own class so as not to fall out of scope. In the code snippet, it is declared on the heap and would delete itself after you setup the signals and return. You must allocate it dynamically and parent it to your own object, or make it a member variable that you manage. Do not use the declaration as it is written. I can't imagine how they arrived at the code snippet in the documentation unless it was a console application that busy-wait polled the status of the reply, but then they wouldn't have suggested connecting to signals to your own slots, so its very misleading.



  • My issue is not related to what you say since my network manager is a member a class in my code and is not declared on the stack the issue is a Bug in QT 4.8.1 which as been resolved in 4.8.3.

    Plus me the code wasn't just not sending signals or slots it complety crashed my application.

    [quote author="okachobi" date="1350329767"]I arrives at this post while searching for a problem I was having with QHttpMultiPart not working. It simply was not making the post and never calling any of the signal handlers. I have since figured out the problem, and wanted to drop some breadcrumbs here for anyone else who is in a similar situation.

    The code snipped in the 4.8 QT manual will not work if cut and paste into a method. It mentions connecting the signals to your slots at the end as if the author of the snippet intended for it to be used in an event driven app, but they declared a local QNetworkAccessManager that will fall out of scope if a method returns and it will never complete the post. They even reparented the file and the multipart objects as if it was a snippet ready to be pasted into a method.

    It took me forever to find this problem because those things were misleading. Indeed, the QNetworkAccessManager should be allocated dynamically and parented to your own class so as not to fall out of scope. In the code snippet, it is declared on the heap and would delete itself after you setup the signals and return. You must allocate it dynamically and parent it to your own object, or make it a member variable that you manage. Do not use the declaration as it is written. I can't imagine how they arrived at the code snippet in the documentation unless it was a console application that busy-wait polled the status of the reply, but then they wouldn't have suggested connecting to signals to your own slots, so its very misleading. [/quote]


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.