[Qt-interest] QNetworkAccessManager and a QHash of QNetworkReply pointers

Thiago Macieira thiago at kde.org
Mon Sep 6 10:57:51 CEST 2010


Em Segunda-feira 06 Setembro 2010, às 09:33:37, Juha Ruotsalainen escreveu:
> Hi there,
> 
> My Friday was spent tracking down this mysterious bug. At least mysterious
> to me...
> 
> Our application uses a QNetworkAccessManager (NAM) to perform all net
> access. The QNetworkReply pointers that NAM's get routine returns are
> stored into a QHash where reply pointers are keys into the hash and values
> consist of a QPair<bool, some_enum_type>.
> 
> NAM's and reply's finished signals and reply's readyRead are connected to
> respective handler slots in the application, let's call them namFin,
> repFin, repRead. namFin's task is to collectively remove items from the
> hash once once network fetches complete and call reply's deleteLater().
> 
> What I noticed on Friday was that:
> 1. namFin was called before repFin. IMHO, I think that it's illogical, I
> would imagine that the NAM would emit finished() once reply has
> finished(), being a _manager_ after all.

Hello Juha

In fact, the two signals are emitted at the same time. It just so happens 
that, due to construction, the manager's signal arrives earlier.

The code:
QNetworkReply *QNetworkAccessManager::get(const QNetworkRequest &request)
{
    return d_func()-
>postProcess(createRequest(QNetworkAccessManager::GetOperation, request));
}

and:
QNetworkReply *QNetworkAccessManagerPrivate::postProcess(QNetworkReply *reply)
{
    Q_Q(QNetworkAccessManager);
    QNetworkReplyPrivate::setManager(reply, q);
    q->connect(reply, SIGNAL(finished()), SLOT(_q_replyFinished()));
[...]
}

The code above will connect the reply's SIGNAL(finished()) to a slot in the 
manager, which in turn emits its own signal. By construction, it will always 
connect before you receive the pointer and connect your own signals.

That in turn means that you always get the manager's signal first.

But like others have said, the two signals mean exactly the same thing, so you 
should handle one or the other, not both.

> 2. When our application starts up, there are two network fetches that work
> as planned, and they are not handled in parallel: first we make a software
> update check, once that finishes we check if some client-specific settings
> have changed on our server. Here the logic works as planned: namRep
> removes autoupdater's reply from the hash, client data checker is added to
> the hash and promptly removed once that fetch completes.
> 
> 3. But, the phase of app startup fails: we start to download data from five
> servers and NAM operates those fetches in parallel. namFin tries to remove
> keys&values from the hash using hash's remove function, but nothing was
> actually removed from the hash. This caused an access violation exception
> when using the application since our app was of the opinion that there is
> a fetch going on (there are entries in the hash), but the underlaying
> system (OS/Qt framework) had already freed the memory related to that
> pointer.

I didn't get this. Can you provide a sample code showing the issue/

> 4. When I relocated the hash remove function call to repFin instead of
> namFin the hash entry logic started to work.
> 
> Is my problem in the order of finished() signals? Is the combination of
> calling deleteLater for a reply before the reply itself has finished
> poisonous? What kind of magic is going on in the background?

No, that shouldn't be an issue.

-- 
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
  Senior Product Manager - Nokia, Qt Development Frameworks
      PGP/GPG: 0x6EF45358; fingerprint:
      E067 918B B660 DBD1 105C  966C 33F5 F005 6EF4 5358
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 190 bytes
Desc: This is a digitally signed message part.
Url : http://lists.qt-project.org/pipermail/qt-interest-old/attachments/20100906/0f1f9403/attachment.bin 


More information about the Qt-interest-old mailing list