PDA

View Full Version : Architecture to eliminate "children and parent that is in a different thread"



CPPProger
18th June 2020, 15:18
I need call QSslSocket into grpc method (https://www.grpc.io/docs/languages/cpp/):


class GreeterServiceImpl final : public Greeter::Service {
Status SayHello(ServerContext* context, const HelloRequest* request, HelloReply* reply) override {
mySslClient.setHostName(/*...*/);
// ...
return Status::OK;
}

MySslClient mySslClient;
};


MySslClient looks like that:


MySslClient::MySslClient(QObject *parent) :
QObject(parent),
mSocket(new QSslSocket(this))
{
QSslConfiguration config = mSocket->sslConfiguration();
//...


As a result, I get an error


QObject: Cannot create children for a parent that is in a different thread.
(Parent is QSslSocket(0x55f14d7adf60), parent's thread is QThread(0x55f14d7ad700), current thread is QThread(0x7fc3fc3faf60)


Can this problem be resolved?

d_stranz
18th June 2020, 18:55
Can this problem be resolved?

Instead of creating your QSslSocket instance in the MySslClient constructor, create it in the same thread where you create the MySslClient instance and pass the pointer in as an additional argument to the MySslClient constructor. Basically, any QObjects that have a parent-child relationship all must be created in the same thread. So any children of MySslClient have to be created in the same thread where the MySslClient instance (and its parent QObject) are created.

CPPProger
22nd June 2020, 18:22
Instead of creating your QSslSocket instance in the MySslClient constructor, create it in the same thread where you create the MySslClient instance and pass the pointer in as an additional argument to the MySslClient constructor. Basically, any QObjects that have a parent-child relationship all must be created in the same thread. So any children of MySslClient have to be created in the same thread where the MySslClient instance (and its parent QObject) are created.

Unfortunately, it didn’t work out. I get gRPC helloworld example https://github.com/plasticbox/grpc-windows/tree/master/grpc_helloworld/src



class GreeterServiceImpl final : public Greeter::Service {

public:

// begin attempt 1
QSslSocket* mSocket;
void setSslSocket(QSslSocket *socket = nullptr) {
mSocket = socket;
}
// end attemt 1

Status SayHello(ServerContext* context, const HelloRequest* request, HelloReply* reply) override {

// begin attemt 1
QSslConfiguration config = mSocket->sslConfiguration();
config.setPeerVerifyMode(QSslSocket::VerifyNone);
config.setProtocol(QSsl::SecureProtocols);
mSocket->setSslConfiguration(config);
mSocket->connectToHostEncrypted("google.com", 8080);
// end attemt 1

std::string prefix("Hello ");
reply->set_message(prefix + request->name());
return Status::OK;
}


};





void RunServer() {
std::string server_address("0.0.0.0:50051");
GreeterServiceImpl service;

// begin attemt 1
QSslSocket* sok = new QSslSocket;
service.setSslSocket(sok);
// end attemt 1
...
server->Wait();
}

int main(int argc, char** argv) {
QCoreApplication a(argc, argv);
RunServer();
return a.exec();
}





$ ./server
Server listening on 0.0.0.0:50051
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QSslSocket(0x56117c127520), parent's thread is QThread(0x56117c120800), current thread is QThread(0x7fa828004510)
^C

ChristianEhrlicher
23rd June 2020, 14:59
You still don't create the socket in the run thread but in the main thread...

CPPProger
24th June 2020, 09:07
You still don't create the socket in the run thread but in the main thread...

Directly inside the gRPC method, the socket also does not want to work.



class GreeterServiceImpl final : public Greeter::Service {
public:
Status SayHello(ServerContext* context, const HelloRequest* request, HelloReply* reply) override {
// begin attempt 2
QSslSocket mSocket;
QSslConfiguration config = mSocket.sslConfiguration();
config.setPeerVerifyMode(QSslSocket::VerifyNone);
config.setProtocol(QSsl::SecureProtocols);
mSocket.setSslConfiguration(config);
mSocket.connectToHostEncrypted("google.com", 8080);
// end attemt 2
std::string prefix("Hello ");
reply->set_message(prefix + request->name());
return Status::OK;
}
};

void RunServer() {
std::string server_address("0.0.0.0:50051");
GreeterServiceImpl service;
grpc::EnableDefaultHealthCheckService(true);
grpc::reflection::InitProtoReflectionServerBuilder Plugin();
ServerBuilder builder;
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
builder.RegisterService(&service);
std::unique_ptr<Server> server(builder.BuildAndStart());
std::cout << "Server listening on " << server_address << std::endl;
server->Wait();
}

int main(int argc, char** argv) {
QCoreApplication a(argc, argv);
RunServer();
return a.exec();
}




QObject: Cannot create children for a parent that is in a different thread.
(Parent is QSslSocket(0x556688f2a520), parent's thread is QThread(0x556688f23800), current thread is QThread(0x7fe7a8004510)


Added after 21 minutes:

I also tried to connect Qt and gRPC with the inclusion of a signal in the server. The latter would help connect the two frameworks.


class GreeterServiceImpl final : public Greeter::Service, public QObject {
Q_OBJECT
public:
Status SayHello(ServerContext* context, const HelloRequest* request, HelloReply* reply) override {
std::string prefix("Hello ");
reply->set_message(prefix + request->name());
emit message();
return Status::OK;
}
signals:
void message();
};

But it failed


In function `GreeterServiceImpl::GreeterServiceImpl()':
error: undefined reference to `vtable for GreeterServiceImpl'
In function `GreeterServiceImpl::~GreeterServiceImpl()':
error: undefined reference to `vtable for GreeterServiceImpl'
error: collect2: error: ld returned 1 exit status