Open iamazeem opened 8 years ago
@iamAzeem I can't reproduce this error
i'm using g++ 5/6
and clang 3.8/3.9
and Qt 5.6.2 / 5.7
under Ubuntu
16.04.1 server and MacOS
10.11.6.
both Release and Debug builds are normally functional.
@azadkuh : Thank you for your response.
Well, here's the complete scenario:
Specs
- Windows 7 (32-bit) - VM
- Qt 5.7 (MinGW)
- Optimization: O3 + Os
- RTTI + exceptions are turned off
I've built QHttp separately, put the .a
and .dll
files with my project and tried to link it.
Now, when I run this from IDE in Debug mode, I get this error on console:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QCoreApplication(0x22fe9c), parent's thread is QThread(0x2e1ed8), current thread is QThread(0x2eef20)
And, the server doesn't accept any requests (something to do with signals).
I'm not using commondir.pri
as have been used in the examples.
Another thing that I've noticed is that when I test the server (when it is running under Release), the HTTP request when partial kind-of blocks the server. The server doesn't respond. Is there any timeout for reading requests? I looked at the code and I didn't see any QNetworkAccessManager
in it. Wouldn't it be more efficient if the new features are used? Just saying.
You might wanna suggest how to use QHttp as a library - the preferred way.
Thanks a lot!
~ AZEEM ~
@iamAzeem
I don't have a win machine right now, but will test it if i find some, there is no difference between release / debug mode in this regard.
as a general rule of thumb, the QObject
instances are not freely movable between threads.
see here.
you have to use all QObject
instances on a single thread or add a message loop to the worker threads (the reason why aQObject
on a child thread won't receive any signal or message).
the qhttp server
never blocks (at least by design), can you describe more or leak some code to show where you actually face a blocking call?
@azadkuh
Yes. I also do believe that there should not be any difference in different modes.
Regarding your comment about threading, if I want to run the QHttpServer
with a GUI, I just have to start the QHttpServer
first then run the GUI. Right?
Well, here's the minimal code example that works in Release mode
and shows the error in Debug mode
. The function runServer()
is from one of the examples without change.
Here's the .pro
file:
QT += core network
QT -= gui
CONFIG += c++11 c++14
TARGET = QhttpTest-HelloWorld
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
win32: LIBS += -L$$PWD/../../../../qhttp/qhttp/xbin/ -lqhttp
INCLUDEPATH += $$PWD/../../../../qhttp/qhttp/src
DEPENDPATH += $$PWD/../../../../qhttp/qhttp/src
Here is the main.cpp
file:
#include <QCoreApplication>
#include <QDebug>
#include "qhttpserver.hpp"
#include "qhttpserverresponse.hpp"
#include "qhttpserverrequest.hpp"
#include "qhttpclient.hpp"
#include "qhttpclientrequest.hpp"
#include "qhttpclientresponse.hpp"
void runServer(const QString& portOrPath)
{
using namespace qhttp::server;
qDebug() << "Running server...";
QHttpServer server(qApp);
// listening tcp port or Unix path
server.listen(portOrPath, [](QHttpRequest* req, QHttpResponse* res) {
req->collectData();
req->onEnd([req, res](){
res->setStatusCode(qhttp::ESTATUS_OK); // status 200
res->addHeader("connection", "close"); // optional(default) header
int size = req->collectedData().size();
auto message = [size]() -> QByteArray {
if ( size == 0 )
return "Hello World!\n";
char buffer[65] = {0};
qsnprintf(buffer, 64, "Hello!\nyou've sent me %d bytes!\n", size);
return buffer;
};
res->end(message()); // reponse body data
});
const auto& h = req->headers();
// optionally let the clients to shut down the server
if ( h.keyHasValue("command", "quit") ) {
printf("a client sends a quit command.\nserver quits.\n");
QCoreApplication::quit();
return;
}
// just for fun! print meta information:
qDebug("\n--> %s : %s",
qhttp::Stringify::toString(req->method()),
qPrintable(req->url().toString().toUtf8())
);
qDebug("[Headers (%d)]", h.size());
h.forEach([](auto iter) {
qDebug(" %s : %s",
iter.key().constData(),
iter.value().constData()
);
});
});
if ( !server.isListening() ) {
fprintf(stderr, "failed. can not listen at port %s!\n", qPrintable(portOrPath));
return;
}
qApp->exec(); // application's main event loop
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
runServer( "8080" );
return 0;
}
Here's the output of compilation for Debug
:
08:35:05: Running steps for project QhttpTest-HelloWorld...
08:35:05: Configuration unchanged, skipping qmake step.
08:35:05: Starting: "C:\Qt\Qt5.7.0\Tools\mingw530_32\bin\mingw32-make.exe"
C:/Qt/Qt5.7.0/Tools/mingw530_32/bin/mingw32-make -f Makefile.Debug
mingw32-make[1]: Entering directory 'C:/Users/Azeem/Documents/QhttpTest-HelloWorld/build'
g++ -c -pipe -fno-keep-inline-dllexport -g -std=gnu++1y -frtti
-Wall -Wextra -fexceptions -mthreads
-DUNICODE -DQT_QML_DEBUG -DQT_NETWORK_LIB -DQT_CORE_LIB
-I..\..\QhttpTest-HelloWorld -I. -IC:\qhttp\qhttp\src
-IC:\Qt\Qt5.7.0\5.7\mingw53_32\include
-IC:\Qt\Qt5.7.0\5.7\mingw53_32\include\QtNetwork
-IC:\Qt\Qt5.7.0\5.7\mingw53_32\include\QtCore -Idebug
-IC:\Qt\Qt5.7.0\5.7\mingw53_32\mkspecs\win32-g++ -o debug\main.o ..\main.cpp
g++ -Wl,-subsystem,console -mthreads -o debug\QhttpTest-HelloWorld.exe debug/main.o
-LC:\qhttp\qhttp\xbin -lqhttp
-LC:\Qt\Qt5.7.0\5.7\mingw53_32\lib
C:\Qt\Qt5.7.0\5.7\mingw53_32\lib\libQt5Networkd.a
C:\Qt\Qt5.7.0\5.7\mingw53_32\lib\libQt5Cored.a
mingw32-make[1]: Leaving directory 'C:/Users/Azeem/Documents/QhttpTest-HelloWorld/build'
08:35:07: The process "C:\Qt\Qt5.7.0\Tools\mingw530_32\bin\mingw32-make.exe" exited normally.
08:35:07: Elapsed time: 00:02.
Here's the compiler output for Release
:
08:34:12: Running steps for project QhttpTest-HelloWorld...
08:34:12: Configuration unchanged, skipping qmake step.
08:34:12: Starting: "C:\Qt\Qt5.7.0\Tools\mingw530_32\bin\mingw32-make.exe"
C:/Qt/Qt5.7.0/Tools/mingw530_32/bin/mingw32-make -f Makefile.Release
mingw32-make[1]: Entering directory 'C:/Users/Azeem/Documents/build-QhttpTest-HelloWorld-Desktop_Qt_5_7_0_MinGW_32bit-Release'
g++ -c -pipe -fno-keep-inline-dllexport -O2 -std=gnu++1y -frtti
-Wall -Wextra -fexceptions -mthreads
-DUNICODE -DQT_NO_DEBUG -DQT_NETWORK_LIB -DQT_CORE_LIB
-I..\QhttpTest-HelloWorld -I.
-I..\..\..\..\qhttp\qhttp\src
-I..\..\..\..\Qt\Qt5.7.0\5.7\mingw53_32\include
-I..\..\..\..\Qt\Qt5.7.0\5.7\mingw53_32\include\QtNetwork
-I..\..\..\..\Qt\Qt5.7.0\5.7\mingw53_32\include\QtCore
-Irelease -I..\..\..\..\Qt\Qt5.7.0\5.7\mingw53_32\mkspecs\win32-g++
-o release\main.o ..\QhttpTest-HelloWorld\main.cpp
g++ -Wl,-s -Wl,-subsystem,console -mthreads -o release\QhttpTest-HelloWorld.exe release/main.o
-LC:\qhttp\qhttp\xbin -lqhttp
-LC:\Qt\Qt5.7.0\5.7\mingw53_32\lib
C:\Qt\Qt5.7.0\5.7\mingw53_32\lib\libQt5Network.a
C:\Qt\Qt5.7.0\5.7\mingw53_32\lib\libQt5Core.a
mingw32-make[1]: Leaving directory 'C:/Users/Azeem/Documents/build-QhttpTest-HelloWorld-Desktop_Qt_5_7_0_MinGW_32bit-Release'
08:34:14: The process "C:\Qt\Qt5.7.0\Tools\mingw530_32\bin\mingw32-make.exe" exited normally.
08:34:14: Elapsed time: 00:02.
Blocking was not for the whole server actually. It's for the request that is not well-formed.
I'm using netcat
for testing the server and Chrome's postman
extension. So, sending the request like this GET / HTTP/1.1\r\n\r\n
would work fine. But, sending only GET\r\n\r\n
or GET \r\n \ \r\n HTTP/1.1 \r\n\r\n
or any of combination won't return. The server would be serving other requests just fine. What happens to the ill-formed requests? I've got Bad Request
also for some requests but not for the ones I mentioned earlier. I'd like you to shed some light on this.
Regarding moving to thread, in fact, I'm not doing anything special about threading here. I was using QHttp
in my project and spent a lot of time about this error. Then, I decided to validate it in isolation before embedding it in the project. So, here it is. I looked at other projects but found it quite useful and it may evolve with time and may be the first choice for writing Qt-specific restful services.
BTW, thanks a lot for writing this in the first place! I really appreciate your help and effort in this regard!
~ AZEEM ~
@azadkuh
I've tested it with GUI and the server is working fine with GUI app.
But, I've an issue that server.isListening()
is not working or there is some kind of delay here.
For an existing bound port, isListening()
is supposed to return false
but it does not and obviously the server does not run if the port is already occupied. Any suggestion or fix?
Don't know if is related to this kind of error but i had the same problem in debug mode. Turn out i was using the wrong .dll, was the one produced by the release mode. I switched then to the debug .dll and now it works. Also did a test using the debug dll in release mode and run without problems.
I've got this error for all the examples. Even for my own code for starting a simple server issued this warning. Couldn't find any issue here.
Release mode is fine but debug mode wouldn't let you run it. Debugger shows a chain of exceptions generated here.
Assembly by the debugger:
I may be wrong but it's a serious bug. I'd appreciate if you could elaborate on this.
Thanks!