PDA

View Full Version : QUrlOperator doesn't emit finished signal



hayati
22nd March 2007, 15:15
I want to get a php page via QUrlOperator, but url should be entered by end users. So url may belong to unreachable host. QT Docs states that QUrlOperator always - whether operation succeeds or fails - emits a finished signal. But amazingly i don't get always. Actually after a while i don't get anymore.
More info to repliers:
1- qInitNetwork... function is in the main so it's called.
2- I get finished signals at least once.

i'll also give you some source code to test it or find what's wrong with it.
the program works as; one widget (which is mainwidget of application) opens another widget with a timeout continuously, then the opened widget tries to reach a url which is unreachable. When it gets finished signal it closes itself.

So it works for five or more times, but after an unknown times of timer timeout program does not get finished signals.

Notes:
FileReader_ and MainUI_ are subclasses of QWidget it doesn't have any other subwidgets or operations.



// header which uses qurloperator
#ifndef FILEREADER_H
#define FILEREADER_H

#include "FileReader_.h"

class QUrlOperator;
class QNetworkOperation;

class FileReader : public FileReader_
{
Q_OBJECT

public:
FileReader(QWidget* parent = 0, const char* name = 0, WFlags fl = 0 );
~FileReader();

public slots:
void stateChangedSlot(int state,const QString&);
void finishedSlot(QNetworkOperation *operation);

private:
QUrlOperator* m_op;
};

#endif

// qurloperator using class's imp.
#include <qurloperator.h>
#include <qnetwork.h>

#include <iostream>

#include "filereader.h"

using namespace std;

FileReader::FileReader(QWidget* parent, const char* name, WFlags fl)
: FileReader_(parent,name,fl)
{
// host part of url, which is here asdfasdf, should be unreachable. So host should not exist on network
m_op = new QUrlOperator("http://asdfasdf/asdf/abcd.php");

connect(m_op, SIGNAL(connectionStateChanged(int,const QString&)), SLOT(stateChangedSlot(int,const QString&)));
connect( m_op, SIGNAL(finished(QNetworkOperation*)), SLOT(finishedSlot(QNetworkOperation*)));

m_op->get();
}

void FileReader::stateChangedSlot(int state,const QString& data)
{
cout << "conn state changed to: " << data.ascii() << endl;

switch( state ){
case QNetworkProtocol::ConConnected:
cout << "CONNECTED" << endl;
break;
case QNetworkProtocol::ConClosed:
cout << "CONNECTION CLOSED" << endl;
break;
}
}

void FileReader::finishedSlot(QNetworkOperation *operation)
{
switch( operation->operation() ){
case QNetworkProtocol::OpGet:
if ( operation->state() == QNetworkProtocol::StFailed ) {
cerr << "finished but there is an error..." << endl;
}
else if ( operation->state() == QNetworkProtocol::StDone ) {
cout << "connection successfully finished..." << endl;
}
}

close(true);
}

FileReader::~FileReader()
{
delete m_op;
}

// header of opening widget
#ifndef MAINUI_H
#define MAINUI_H

#include "MainUI_.h"

class QTimer;
class FileReader;

class MainUI : public Form1
{
Q_OBJECT

public:
MainUI(QWidget* parent = 0, const char* name = 0, WFlags fl = 0 );

public slots:
void refreshInfo();

protected:
QTimer* m_timer;
FileReader* fileReader;
};

#endif

// imp.
#include <qtimer.h>

#include "mainui.h"
#include "filereader.h"

MainUI::MainUI(QWidget* parent, const char* name, WFlags fl)
: Form1(parent,name,fl)
{
m_timer = new QTimer(this);

connect(m_timer, SIGNAL(timeout()), SLOT(refreshInfo()));

m_timer->start( 30000 );

fileReader = new FileReader();
fileReader->show();
}

void MainUI::refreshInfo()
{
fileReader = new FileReader();
fileReader->show();
}


// main.cpp
#include <qapplication.h>
#include <qnetwork.h>
#include <stdio.h>
#include <stdlib.h>

#include "mainui.h"

int main(int argc, char *argv[])
{
QApplication app(argc,argv);

qInitNetworkProtocols();

MainUI fr;
app.setMainWidget( &fr );
fr.show();

app.exec();
}



thanks for all replys...

jacek
22nd March 2007, 19:46
Maybe it's because of a memory leak? Where do you delete m_op?

hayati
22nd March 2007, 19:59
yeh i know there is (or are) memory leak. but the problem isn't the memory leak. As you see from the code it just shows the skeleton, in actual program it is deleted but there is no change.
After all even there is a memory leak m_op is created from the beginning. so newly created m_op should get finished signal either way. I applied with the delete m_op but this didn't changed any thing :(
everbody is free to change the code to make it worked. As skeleton shows there isn't any magic operation took place. Amazingly it doesn't emit finished.

i also edited the source code to fix the leak.

what i also tried to stop get progres before to delete m_op with

m_op->stop();
at the destructor but it also makes no sense :(

hayati
23rd March 2007, 08:03
Unfortunately i get neither descriptive reason of the problem nor solution to it.
As the code part of my problem shows, it should be worked but it isn't.
Any help is wellcome.

here is what i get at the console output:
conn state changed to: host asdfasdf found
finished but there is an error...
conn state changed to: host asdfasdf found
finished but there is an error...
conn state changed to: host asdfasdf found
finished but there is an error...
conn state changed to: host asdfasdf found
finished but there is an error...
conn state changed to: host asdfasdf found
conn state changed to: host asdfasdf found
conn state changed to: host asdfasdf found
conn state changed to: host asdfasdf found
conn state changed to: host asdfasdf found
conn state changed to: host asdfasdf found

this goes forever...

as output shows after a while finished signal is not emitted :(

jacek
23rd March 2007, 10:32
as output shows after a while finished signal is not emitted :(
How long does this "while" take? Which Qt version do you use?

hayati
23rd March 2007, 11:14
i use qt3
and from the output it could be said that it's about 120 to 210 seconds at least but it could take long of course because there is no clue about the error. I'm using just the code i've posted to test the situation but even this little code makes the same error.
i think it's goint to a qt bug :(
because it works perfectly when requested web pages are found.

jacek
23rd March 2007, 11:49
i use qt3
There are over 20 versions of Qt3. Which one do you use?

hayati
23rd March 2007, 12:10
right :( it's v3.3.6

and v3.3.3 gives the same result :(

jacek
23rd March 2007, 13:13
right :( it's v3.3.6

and v3.3.3 gives the same result :(
Try Qt 3.3.8. There was some problem with QDns fixed. On my system finished() is always emitted, but the application crashes after a while (it has something to do with event delivery).

hayati
23rd March 2007, 13:23
thanks for the reply,
yes it's obvious that it has some problems internally.
unfortunately i can't use v3.3.8
even so, as you said it gets errors with internal SIGSEGV errors.
I'll use libcurl library for that purpose for now :(
thanks for help.

jacek
23rd March 2007, 13:51
even so, as you said it gets errors with internal SIGSEGV errors.
I didn't say that they are internal errors.

hayati
23rd March 2007, 14:10
yes you didn't say, sorry about misunderstanding.
I'm confused because i get SIGSEGV after my last try to fix the problem :)
That's why i said SIGSEGV, it's what i get, not yours.
If it's undertood like yours i apologize :(

Another amazing thing about the QUrlOperator is;
I placed a single-shot timer as error-interval. When timer is up then even if i don't get finished signal i delete the opened widget, at the destructor i stop m_op, and delete it.
But this time i got SIGSEGV.
In addition, gdb stack trace points out qsocket caused the SIGSEGV.
that's why i said -INTERNAL- error.
I think I get SIGSEGV because m_op opened a QSocket internally but after i delete m_op then m_op deletes QSocket and when system is about to use to deleted socket then SIGSEGV occurs. (just an estimation)
By the way that's not the point of the problem.

Problem is QUrlOperator doesn't emit finished signals after a while :(

jacek
23rd March 2007, 17:16
But this time i got SIGSEGV.
Such fault can occur when you delete an object within event handler and it's usually solved using QObject::deleteLater().


Problem is QUrlOperator doesn't emit finished signals after a while
It looks like this problem doesn't occur on Qt 3.3.8. Try the narrowed-down example from the attachment.

hayati
26th March 2007, 11:22
Thanks for your quick replys. I really appreciated.
I couldn't answer your replys for a while because i got cold.
Unfortunately even v3.3.8 with your test code(main.cpp) fails when id is over 400.
After id value of 400, program didn't received any finished signal at all :(
Perharps you didn't wait as much as program starts failing :(
Because we don't know what is wrong and when the program starts failing best of best of us is to wait for ten minutes at least.
I am sure that my application uses v3.3.8 because i checked it with qVersion() within your test code.

jacek
26th March 2007, 13:59
Unfortunately even v3.3.8 with your test code(main.cpp) fails when id is over 400.
After id value of 400, program didn't received any finished signal at all
I've just tried it again and reached id = 1500 without any signs of failure.

I can't run Valgrind on my system, so I can't check whether the are any problems inside Qt, but try this:

Test() : _id( _nextId++ )
{
std::cerr << "created " << _id << std::endl;
_op = new QUrlOperator("http://test.domain.tld/");

if( _op != 0 ) {
connect( _op, SIGNAL(finished(QNetworkOperation*)), SLOT(finished()) );
if( _op->get() == 0 ) {
std::cerr << "get() failed " << _id << std::endl;
deleteLater();
}
}
else {
std::cerr << "allocation failed " << _id << std::endl;
deleteLater();
}
}

hayati
26th March 2007, 17:25
It's about something different.
I tested main.cpp in my home network then it's like just you mentioned.
So it works perfectly even with v3.3.6 at my home. But what's missing with my job network or what's more.
My home network is very little it has three pc so name resolution could be very fast.
But my job network is quite big (and more will be- over 400 pc).
It has a heavy multicast traffic also. (But I don't think that's the problem) It must be something different. At first I thought it might be a protection from firewall or other network devices (just an estimation), but my network admin said it isn't.
But unfortunately I have no idea :(
By the way I started coding my own url class from curl.
Even if I know that qt has coded it more bugfree than me, I have no other chance to do now unless finding out the way to make it worked.

Thanks for your patience, because I give up counting at 1265 an I satisfied that it's something else :)

jacek
26th March 2007, 20:25
But my job network is quite big (and more will be- over 400 pc).
It has a heavy multicast traffic also.
Then it might be some subtle bug that might possibly have something to do with timeouts. You can try contacting Trolltech and ask whether they can do something about it.