I am developing a multithreaded ROS application involving Qt::QThread-inherited objects producing signals triggering ROS publishers in the ROS node activated in the main() function. Qt signals and the event loop are handled by Qt::QCoreApplication How can one properly organize the connection between the application objects and runner functions? In the ordinary application Qt::QCoreApplication.exec() and ros::spin() functions are blocking.
The solution is quite easy. It is needed to install SIGINT signal handler function that will control the sequence of starting and stopping event loops:
// POSIX signal handler prototype section
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
// Qt section
#include <QCoreApplication>
// ROS section
#include <ros/ros.h>
// SIGINT handler function
void handle_shutdown(int s)
{
ROS_INFO("Shutting down node...");
ros::shutdown(); // Step 1: stopping ROS event loop
QCoreApplication::exit(0); // Step 2: stopping Qt event loop
}
int main(int argc, char** args)
{
// SIGINT handler setup
struct sigaction sigIntHandler;
sigIntHandler.sa_handler = handle_shutdown;
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
sigaction(SIGINT, &sigIntHandler, NULL);
// Instantiating Qt application object
QCoreApplication app(argc, args);
// Instantiating ROS node object
ros::init(argc, args, "witmotion_ros", ros::InitOption::NoSigintHandler);
ros::NodeHandler node("~");
// Running ROS non-blocking event loop
ros::AsyncSpinner spinner(2);
spinner.start();
// Running Qt event loop: blocking call
int result = app.exec();
// Waiting for signal handler's return
ros::waitForShutdown();
// Exit code: from Qt
return result;
}
The option ros::InitOption::NoSigintHandler instructs ROS application object to skip the installation of its own SIGINT handler. This kind of setup allows using freely both Qt signals, events and ROS callbacks without mutual blocks and race conditions. However, the code model is not totally thread-safe, so it is mandatory to handle synchronization of the data in case of bidirectional exchange.
Related
I'm trying to build an automated testing against my simulated FreeRTOS device
Gtest is running in the main thread, the FreeRTOS Simulation is started from the main Thread within a new std::thread.
The challenge is, that the FreeRTOS Simulation might start several threads as well.
The GTest main thread and the freertos simulation thread communicate via a TCP/IP localhost socket with each other (on a real device this can easily replaced by another socket). For a better overview this is not shown in this demo.
int main(int argc,char *argv[])
{
::testing::InitGoogleTest(&argc, argv);
int res = RUN_ALL_TESTS();
return res;
}
and my testsuite looks like this
#include <gtest/gtest.h>
#include <iostream>
#include <memory>
#include <thread>
#include <FreeRTOS.h>
#include <task.h>
#ifdef WIN32
#include <Windows.h>
#endif //WIN32
class TestFixture : public ::testing::Test
{
protected:
///the Running Simulation
static std::unique_ptr<std::thread> m_pSim;
/**
* #brief Setup this whole testsuite =>only launch Sim once (and not in every test)
*/
static void SetUpTestSuite();
/**
* #brief Trys to kill freertos (Freertos is not designed to be stopped once running)
*/
static void TearDownTestSuite();
};
std::unique_ptr<std::thread> TestFixture::m_pSim;
void TestFixture::SetUpTestSuite()
{
//launch FreeRTOS_Demo starts some FreeRTOS Tasks and calls vTaskStartScheduler()
m_pSim = std::make_unique<std::thread>(&LaunchFreeRTOS_Demo);
}
void TestFixture::TearDownTestSuite()
{
if (m_pSim)
{
/*
* FreeRTOS is not designed to be stopped once started
* detaching the thread will hopefully enable the OS to properly delete the
* FreeRTOS Thread
* */
//stop all running threads
const auto vecTaskInfo = getAllRunningFreeRTOSTasks();
for (const auto& singleTask : vecTaskInfo)
{
vTaskSuspend(singleTask.xHandle);
vTaskDelete(singleTask.xHandle);
}
vTaskSuspendAll();
auto natitveHandle = m_pSim->native_handle();
m_pSim->detach();
if (natitveHandle)
{
#ifdef WIN32
TerminateThread(natitveHandle, 99);
#endif // WIN32
}
}
}
TEST_F(TestFixture, Foo)
{
std::cout << "Running Testclient" << std::endl;
EXPECT_TRUE(true);
}
So my Question: how can I terminate the Test and get the results from GTest. I do not need to shutdown freertos properly since this executable is closed after the test.
What did I try so far:
I tried not to actually close freertos (I left out the
TearDownTestSuite() part)). =>GTest Thread exit properly but the
program seamed to be endlessly waiting for the FreeRTOS Tasks to
terminate. Program does not quit.
The TearDown() Solution posted above =>FreeRTOS Tasks still seam to
be running. Program does not quit
could you help me out here? I know that shooting running threads down is not a nice thing to do, but since freertos is designed as an embedded application it is not designed to be terminated.
I was wondering how I can run a function when closing the terminal (I'm on Linux) of my Qt Console Application. I have a 'static' class which holds all the variables I need (I know I can use singleton but I like this way better) and it has a function called destroy, this will delete all pointers).
So this is my .cpp of the 'static' class:
#include "engine.h"
logging* engine::m_logging;
tcp_listener* engine::m_tcp_listener;
void engine::initialize()
{
engine::m_logging = new logging();
engine::m_logging->write_line("Initializing Fullmoon Messenger server...");
engine::m_tcp_listener = new tcp_listener();
engine::m_tcp_listener->start("127.0.0.1", 30000);
}
void engine::destroy()
{
delete engine::m_logging;
}
logging* engine::get_logging()
{
return engine::m_logging;
}
And this is my main.cpp:
#include <QCoreApplication>
#include "engine.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
engine::initialize();
return a.exec();
}
How can I call engine::destroy when closing the application? I assume there's a signal for it.
You need to handle the POSIX signal SIGHUP for this.
(Note: POSIX signals are something completely different than Qt signals, so they're not handled with "slots". Don't confuse them.)
Note that your options for what to do in a POSIX signal handler are very limited. The man page signal(7) lists the functions which are safe to be called. In the comments to this answer, Kuba Ober pointed out that you should to stick to the official documentation for handling POSIX signals in Qt applications. But since the process as explained in the documentation is quite complicated, I wrapped it in a reusable class PosixSignalProxy, converting POSIX signals to Qt signals.
If you use this proxy class you just have to write:
PosixSignalProxy<SIGHUP> sighupProxy;
QObject::connect(&sighupProxy, &PosixSignalProxyBase::receivedSignal, []{
engine::destroy();
});
The class is found at the bottom of this post.
Note that only one instance of a PosixSignalProxy can be created for each POSIX signal type. If you need to do multiple things when receiving a signal, you can however connect to the Qt signal multiple times.
Also, you might be interested in similar signals for different external reasons for quitting your application, such as killing it or hitting Ctrl+C in the terminal window.
SIGHUP (as in the example above): when the terminal window was closed (and the parent process was destroyed)
SIGINT: when the user hits Ctrl+C - Note that when you handle this signal you need to quit at the end of the handler since your process is responsible of finally quitting itself. You overwrite this default behavior and have the option not to only cleanup stuff but also to ignore the user's wish to quit the application.
SIGTERM: when the process is killed with e.g. kill (not to be confused with SIGKILL which is a more aggressive way to kill a process; you can't handle that one)
Here is the class definition:
posixsignalproxy.h
#ifndef POSIXSIGNALPROXY_H
#define POSIXSIGNALPROXY_H
#include <QObject>
class QSocketNotifier;
typedef void (*PosixSignalHandlerType) (int);
// Helper base class (no template) - Do not use this class directly.
class PosixSignalProxyBase : public QObject
{
Q_OBJECT
public:
PosixSignalProxyBase(
QObject *parent,
int (&sockets)[2],
int posixSignalNumber,
PosixSignalHandlerType posixSignalHandler,
int posixSignalFlags);
~PosixSignalProxyBase();
signals:
/**
* Qt signal which is emitted right after receiving and handling the POSIX
* signal. In the Qt signal handler (slot) you are allowed to do anything.
*/
void receivedSignal();
protected:
static void staticSignalHandler(int (&sockets)[2]);
private slots:
void handleSignal();
private:
int (&sockets)[2];
QSocketNotifier *notifier;
};
// Actual proxy class, defining its own static proxy signal handler function and sockets.
template <int signum>
class PosixSignalProxy : public PosixSignalProxyBase
{
public:
PosixSignalProxy(QObject *parent = nullptr, int posixSignalFlags = 0) :
PosixSignalProxyBase(parent, mySockets, signum, &posixSignalHandler, posixSignalFlags)
{}
PosixSignalProxy(int posixSignalFlags) :
PosixSignalProxy(nullptr, posixSignalFlags)
{}
static void posixSignalHandler(int) {
PosixSignalProxyBase::staticSignalHandler(mySockets);
}
private:
static int mySockets[2];
};
template <int signum>
int PosixSignalProxy<signum>::mySockets[2];
#endif // POSIXSIGNALPROXY_H
posixsignalproxy.cpp
#include "posixsignalproxy.h"
#include <QSocketNotifier>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <signal.h>
PosixSignalProxyBase::PosixSignalProxyBase(QObject *parent, int (&sockets)[2], int posixSignalNumber, PosixSignalHandlerType posixSignalHandler, int posixSignalFlags) :
QObject(parent),
sockets(sockets)
{
if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sockets))
qFatal("PosixSignalProxy: Couldn't create socket pair");
notifier = new QSocketNotifier(sockets[1], QSocketNotifier::Read, this);
connect(notifier, SIGNAL(activated(int)), this, SLOT(handleSignal()));
struct sigaction sa;
sa.sa_handler = posixSignalHandler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = posixSignalFlags;
if (sigaction(posixSignalNumber, &sa, 0) > 0)
qFatal("PosixSignalProxy: Couldn't register POSIX signal handler");
}
PosixSignalProxyBase::~PosixSignalProxyBase()
{
delete notifier;
}
void PosixSignalProxyBase::staticSignalHandler(int (&sockets)[2])
{
char tmp = 1;
::write(sockets[0], &tmp, sizeof(tmp));
}
void PosixSignalProxyBase::handleSignal()
{
notifier->setEnabled(false);
char tmp;
::read(sockets[1], &tmp, sizeof(tmp));
// Here, we're allowed to do Qt stuff.
emit receivedSignal();
notifier->setEnabled(true);
}
You're looking for QCoreApplication::aboutToQuit if you want to use a signal.
Better idea IMO is for engine not to have static functions but to manage its resources properly in its destructor. You can make it a singleton if you want.
I have a lot of existing code using Qt, and more specifically Qt signals and slots to time specific actions.
Now I need to use this code within a new application which is not a Qt application (and cannot be - I am writing a plugin to visual studio). Anyway - how can I get the existing code to actually intercept the signals and activate the relevant slots?
Do I need to somehow create a dummy Qt application? If so - how do I cause it to process the signals without becoming a blocking loop to the rest of my code?
It seems that if you write something like this, the "Test" message is still printed even though there is no event loop, so this could be a clue:
#include <QObject>
#include <QCoreApplication>
#include <QDebug>
class MyClass : public QObject
{
Q_OBJECT
public:
explicit MyClass(QObject *parent) : QObject(parent) {}
void testMethod() { emit testSignal(); }
signals:
void testSignal();
public slots:
void testSlot() { qDebug() << "Test"; }
};
#include "main.moc"
int main(int argc, char **argv)
{
// QCoreApplication coreApplication(argc, argv);
MyClass myObject(0);
QObject::connect(&myObject, SIGNAL(testSignal()), &myObject, SLOT(testSlot()));
myObject.testMethod();
// return coreApplication.exec();
return 0;
}
This way, you would still need Qt, but you could avoid having a "blocking" event loop. However, it might be simpler to just rearrange the code from the signal-slot layering to direct calls, depending on how many direct calls you would need to do for a signal emitted.
This is a common problem when using ASIO and Qt together. The solution I have found is to make a Broker object, and run the Qt and ASIO loops on their own threads. The Broker is the target for emit calls to the ASIO message queue, and the emitter to the Qt message queue. Take care of the syncronisation/data copying in the Broker.
I am developing an application that uses C++ and compiles using Linux GNU C Compiler.
I want to invoke a function as the user interrupts the script using Ctrl + C keys.
What should I do? Any answers would be much appreciated.
When you press Ctr + C, the operating system sends a signal to the process. There are many signals and one of them is SIGINT. The SIGINT ("program interrupt") is one of the Termination Signals.
There are a few more kinds of Termination Signals, but the interesting thing about SIGINT is that it can be handled (caught) by your program. The default action of SIGINT is program termination. That is, if your program doesn't specifically handle this signal, when you press Ctr + C your program terminates as the default action.
To change the default action of a signal you have to register the signal to be caught. To register a signal in a C program (at least under POSIX systems) there are two functions
signal(int signum, sighandler_t handler);
sigaction(int signum, const struct sigaction *act,
struct sigaction *oldact);.
These functions require the header signal.h to be included in your C code. I have provide a simple example of the signal function below with comments.
#include <stdio.h>
#include <stdlib.h>
#include <signal.h> // our new library
volatile sig_atomic_t flag = 0;
void my_function(int sig){ // can be called asynchronously
flag = 1; // set flag
}
int main(){
// Register signals
signal(SIGINT, my_function);
// ^ ^
// Which-Signal |-- which user defined function registered
while(1)
if(flag){ // my action when signal set it 1
printf("\n Signal caught!\n");
printf("\n default action it not termination!\n");
flag = 0;
}
return 0;
}
Note: you should only call safe/authorized functions in signal handler. For example avoid calling printf in signal handler.
You can compile this code with gcc and execute it from the shell. There is an infinite loop in the code and it will run until you send a SIGINT signal by pressing Ctr + C.
Typing CtrlC normally causes the shell to send SIGINT to your program. Add a handler for that signal (via signal(2) or sigaction(2)), and you can do what you like when CtrlC is pressed.
Alternately, if you only care about doing cleanup before your program exits, setting up an exit handler via atexit(3) might be more appropriate.
You can use the signal macro.
Here is an example of how to deal with it:
#include <signal.h>
#include <stdio.h>
void sigint(int a)
{
printf("^C caught\n");
}
int main()
{
signal(SIGINT, sigint);
for (;;) {}
}
Sample output:
Ethans-MacBook-Pro:~ phyrrus9$ ./a.out
^C^C caught
^C^C caught
^C^C caught
^C^C caught
^C^C caught
I need to exec() a QApplication in a thread that is not main (my GUIs must be plugins that can be dynamically loaded and unloaded at runtime, so I have no access to the main thread). Does anyone know of a (relatively) painless way to hack around Qt's restriction against starting QApplication outside of main?
I'm developing in Linux with Qt4 in C++ using gcc4.3.4.
You can start a QApplication in a PThread as below
//main.cpp
#include <iostream>
#include "appthread.h"
int main(int argc, char *argv[]) {
InputArgs args = {argc, argv};
StartAppThread(args);
sleep(10);
return 0;
}
//appthread.h
struct InputArgs{
int argc;
char **argv;
};
void StartAppThread(InputArgs &);
//appthread.cpp
#include <QApplication>
#include <QMainWindow>
#include <QPushButton>
#include "appthread.h"
#include <pthread.h>
void *StartQAppThread(void *threadArg) {
InputArgs *args = (struct InputArgs*) threadArg;
QApplication app(args->argc, args->argv);
QMainWindow w;
w.show();
w.setCentralWidget(new QPushButton("NewButton"));
app.exec();
pthread_exit(NULL);
}
void StartAppThread(InputArgs &args) {
pthread_t thread1;
int rc = pthread_create(&thread1, NULL, StartQAppThread, (void*)&args);
}
If you are using QThread then you already have normal Qt event loop and can just run exec() inside QThread::run() function. While you can't work with GUI objects outside of the main thread you still can interact with them through queued signal/slot connections. Maybe you can try to store pointer to the main thread QThread object and call QObject::moveToThread() to move your GUI objects to the main thread instead of moving QApplication into another thread.
I think it's not really good idea to try to go against toolkit with different kind of hacks and kluges.
Ok, I got something that works! It's not pretty, but it definitely does the job.
Create a QMainWindow derivative with all of your actual GUI code in it and overload the event() function of this class to call this->show()
Create a class (let's call it Runner) which will hold a pointer to your QMainWindow derivative, and give it a run function.
In the Runner::Runner(), start up a thread which will call Runner::run()
In Runner::run() (which is now running in it's own thread) construct a QApplication, and an instantiation of your QMainWindow derivative. Call the exec() function of the QApplication.
Now, when you want to start up your GUI, just post any event to your QMainWindow derivative, and it will show itself!
This solution seems to work very well in Linux, although it really seems to be exploiting some loophole in Qt and may not work on other platforms. Definitely easier than patching Qt though.
Patch Qt, I guess and remove the main thread check, and test if that works for you.
According to
http://bugreports.qt-project.org/browse/QTBUG-7393
that won't work on OS X/Cocoa though, as Cocoa assumes the first thread spawned to be the main/UI thread.
Adding my 2 cents with a fancy lambda and C++ threads:
#include "mainwindow.h"
#include <QApplication>
#include <thread>
int main(int argc, char *argv[])
{
std::thread t1
(
[&]
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
);
t1.join();
}
Here Mainwindow can be your QMainWindow.
A good solution is found in: git#github.com:midjji/convenient_multithreaded_qt_gui.git
then its just e.g.
run_in_gui_thread(new RunEventImpl([](){
QMainWindow* window=new QMainWindow();
window->show();
}));
or whatever code you wish to run in the gui thread.
callable from any thread, at any time, while taking care of setting things up for you in the bg.