How to run QTcpServer in separate thread from GUI in PySide6? - qt

I'm making a PySide6 program with a GUI, backend, and a QTcpServer (which only handles a single connection), and I want all three in separate threads as to never freeze up the GUI.
I read about implementing the run() function in QThread, but the backend and the server are entirely event-driven, so this seems like a bad solution. Is there a way to just place the whole QTcpServer and backend instances in separate threads?

Solution
Note: My TCP_Server is a singleton, not sure if you would need a reference to it otherwise, so it doesn't go out of scope.
class ServerThread(QRunnable):
#Slot()
def run(self):
TCP_Server()
threadpool = QThreadPool()
server = ServerThread()
threadpool.start(server)

Related

Serialize signals/slot QObjects using shared memory

I have two Qt apps sharing a memory segment.
I would like to be able to emit a signal from App2 and trigger a slot from App1.
First off, I need to use QObject::connect() to link the App2 signal to the App1 slot.
Is there a good way to connect two different Qt processes signals/slots mechanisms? I've stumbled upon the qt-remote-signals library to send remote signals, which is using QDataStream to serialize the object. QSharedMemory uses the same class.
Or should I forget about connecting anything and just simulate a signal/slot behaviour?
Write in the memory segment from App2
Read the segment whenever it changes from App1 (how to know when it is updated?)
Emit a custom signal from App1
Trigger a slot from App1
Does that sound realistic ? I'm new to shared memory.
As far as I know, you can't connect Signal/Slot between processes. Also you cannot know 'naturaly' if another process have changed a QSharedMemory.
So I think you'll have to simulate it as you said.
Write in the memory segment from App2
App 1 could be checking periodically the segment, to being aware of changes from App 2. Once a change is done, you directly trigger the slot (you don't really need the signal)
If you need an instantly response (without making the App 1 checking time too small) from App1 you could make them comunicate using QLocalSocket/Server or D-Bus, butin that case you could go all in with them and manage all the comunication, making the QSharedMemory unnecesary.

Initialize QProcess to a process already running

I would like know if it's possible to create a QProcess and initialize it to a process which is already running?
My application starts an other application. So if my application is abnormally closed, when it will be restarted, I would like attach the other application.
You should use an IPC system like e.g. Qt D-Bus on Linux. You then communicate with the other process over the IPC system instead of stdin and stdout.
When your frontend application crashes, then the restarted application can reconnect to the backend process.
Unfortunately, due to the internal architecture of QProcess, there's no support for this. You'd need to copy-paste a bunch of QProcess code to a new class and add the missing functionality yourself.
There's an easier way, though: create a process wrapper that exposes a QProcess via QLocalSocket. The wrapper is simple and shouldn't be crashing. It can self-terminate when the process itself terminates, to prevent dangling wrappers from hanging around. When your application crashes or is terminated, the new instance can try to attach to the local socket if a wrapper exists. If it doesn't exist, then it will spawn a new wrapper.

Qt QTcpSocket waitForReadyRead crashes when socket is closed from a different thread

I am calling waitForReadyRead method of QTcpSocket in a separate thread(pthread) ,
Now if socket is closed from the main thread the application crashes in waitForReadyRead method.
And I am using waitForReadyRead with time out = -1.
Also I cannot use qt signal slot mechanism in my implementation
Can someone Please explain me what is wrong in the above implementation
From the Qt documentation of QTcpThread:
Note: All functions in this class are reentrant.
This means that it is not safe to call one object from multiple threads (read this for more info). Even if you get your code to work somehow it might crash in an older or newer version.
If you really can't use signals/slots then you could set a flag when you want to close the connection and call waitForReadyRead in a loop with a timeout. Then you can poll the flag and close the socket with the waitForReadyRead-thread if it is set.

Sharing data across Qt threads

I'm new to Qt so please excuse the simplicity of the question but I'm a bit confused on the Qt threading. Let's say I have 3 threads: the main default GUI thread, and 2 threads of my own creation (called WorkerThread). Each of my WorkerThreads inherits from QThread and are permanent threads that every so often wake up and send data out a socket and post status on a GUI element. How is the best way to 1) allow the GUI thread to set data in the WorkerThread object that the WorkerThread thread can use? 2) allow the WorkerThread to send status to the GUI thread to be displayed for the user? 3) Allow both WorkerThreads to use the same socket?
It seems from the documentation that when I create a WorkerThread object it is owned by the creating thread (except for the run method that is a new thread). So how does one set data for the new thread to execute on? Must all the data the new thread uses be global? For instance, I would like the GUI to allow the user to select a packet type for each of the WorkerThreads to send when they wake up. I had assumed that I would put in some slots in the WorkerThread that the GUI thread would signal. When the WorkerThread object received a signal to SetPacketType it would set a member variable that the run method references on each iteration. But after reading the documentation I'm not sure that is the way to do it. If the WorkerThread object is owned by the creating thread (GUI thread in this case) then sending signals to it doesn't cross thread boundaries does it?
Also, what is the proper technique for sharing the socket connection across threads?
Thanks in advance.
With Qt, the easiest way to send information between threads is to use signals and slots. Qt automatically uses queued signals for connections between threads (see Qt::ConnectionType), which ensures that a signal can be emitted from one thread, but the slot will be executed in the thread of the receiver object.
If the data being sent between threads (work to be done or status information) is something that Qt can automatically queue (e.g., QStrings, built-in types like int and double, and others), then passing the info as the arguments to the signal/slot is the best way to send the info. If large or complex data is being shared, then you either need to use qRegisterMetaType to allow Qt to copy the data, or pass a pointer to a thread-safe object. Unlike what Pie_Jesu said, the threads do share an address space so you can share pointers; just make sure that one thread's interaction with the shared object won't interfere with another thread's interactions.
QTcpSocket is not thread-safe (it's only reentrant according to Qt's documentation), so if you share the socket you will have to be responsible for ensuring that threads don't use the socket in conflicting ways.

Communication among threads in Qt

I'm working with threads in C++/Qt, each one to establish and mantain a QTcpSocket connection.
The problem is that when a disconnection from network comes, those threads must reconnect in a certain order. That's already working, but I have another problem: I need to know into each thread if only current thread has been disconnected, or all of them have been disconnected.
The first idea I had was to pass every thread a reference to a class where I would be able to store each thread status and check everyone else's.
But then I had an easier idea, and I would like to know if it would work or if it impossible: use Qt's slots and signals.
So, every thread I have comes from the same class, but passing different data to the Ctor. So the idea would be to create a slot and a signal inside that class, connect them and emit the signal passing an ID. Then, every thread's slot would be launched... or I may be completely wrong and the only slot launched would be the one from the very same thread which emited the signal.
Is this possible or not?
First of all, signal-slot connections are done between signals and slots in QObjects, not between threads. Well, a QThread is a QObject, but you really should not derive from a QThread. Do not derive from QThread and you'll be fine.
What you do is:
Get one or more QThreads started (not merely constructed). Those QThreads are just the base Qt classes, don't derive from them. A started raw QThread is blocked, waiting for an event to be posted to its event queue. The default implementation of QThread::run() calls QEventLoop::exec() (or an equivalent). Thus those threads, after starting, don't consume any CPU cycles.
Instantiate a bunch of QObjects. Do all the signal/slot connections as necessary.
Move those objects to one or more QThreads by calling moveToThread(QThread*) on them.
As you see, setting up signal slot connections is done in the usual manner and does not require any special attention. Qt does everything for you, including changing connection types from Qt::DirectConnection to Qt::QueuedConnection when you move the QObjects between threads.
Note that you must not call any methods on those QObjects directly, because you'll be doing so likely from a different thread, so all sorts of bad things will happen as the access is not serialized. You must do any of the below, and only that, in order from fastest to slowest. Note that while #3 is always faster than #4, you need to benchmark between #2 and #3 as it varies.
Post a custom event to the QObject, and handle it in the derived QObject's customEvent(QEvent*) method.
Use the signal-slot connections, and emit signals that got connected to the QObjects' slots.
Use QMetaMethod::invoke on a previously looked up method. The is faster than #4 since the method lookup is done only once in advance.
Use QMetaObject::invokeMethod.
Posting QEvents to QObjects is faster than using signal-slot invocations, because there are no copy constructors called and there's no marshalling done except directly by you upon construction of a QEvent.
Only if profiling/benchmarking shows that event posting is too slow you'd want to look at using QSharedMemory. Having an excessive number of QThreads is counterproductive, you should have probably not more than the number of CPU cores on the system. Using synchronization primitives such as mutexes or semaphores naively requires you to commit way too many threads. You definitely do not want to have one thread per connection! Qt already has an event queue mutex for each QObject, by using the event queue you already use that.
Signal and slot connections are done in run time, i.e. you are connecting specific instances of a class. You cannot emit a signal and "broadcast" it to every instance of your class. Signals between different threads is possible, but maintaining them could be a bit of a hassle (It's all explained pretty well in the documentation).
If I were you, I'd probably look into QSemaphore or QSharedMemory.

Resources