Hy,
I'm writing my first Qt program and getting now in troubles with:
QObject::killTimer: timers cannot be stopped from another thread
QObject::startTimer: timers cannot be started from another thread
My program will communicate to a CANOpen bus for that I'm using the Canfestival Stack. The Canfestival will work with callback methods. To detects timeout in communication I setup a timer function (somehow like a watchdog). My timer package consist out of a "tmr" module, a "TimerForFWUpgrade" module and a "SingleTimer" module. The "tmr" module was originally C programmed so the static "TimerForFWUpgrade" methods will interface it. The "tmr" module will be part of a C programed Firmware update package.
The timer will work as follows. Before a message is sent I will call TMR_Set method. An then in my idle program loop with TMR_IsElapsed we check for a timer underflow. If TMR_IsElapsed I will do the errorhandling. As you see the TMR_Set method will be called continuously and restart the QTimer again and again.
The above noted errors are appearing if I start my program. Can you tell me if my concept could work? Why does this errors appear? Do I have to use additional threads (QThread) to the main thread?
Thank you
Matt
Run and Idle loop:
void run
{
// start communicate with callbacks where TMR_Set is set continously
...
while(TMR_IsElapsed(TMR_NBR_CFU) != 1);
// if TMR_IsElapsed check for errorhandling
....
}
Module tmr (interface to C program):
extern "C"
{
void TMR_Set(UINT8 tmrnbr, UINT32 time)
{
TimerForFWUpgrade::set(tmrnbr, time);
}
INT8 TMR_IsElapsed(UINT8 tmrnbr)
{
return TimerForFWUpgrade::isElapsed(tmrnbr);
}
}
Module TimerForFWUpgrade:
SingleTimer* TimerForFWUpgrade::singleTimer[NR_OF_TIMERS];
TimerForFWUpgrade::TimerForFWUpgrade(QObject* parent)
{
for(unsigned char i = 0; i < NR_OF_TIMERS; i++)
{
singleTimer[i] = new SingleTimer(parent);
}
}
//static
void TimerForFWUpgrade::set(unsigned char tmrnbr, unsigned int time)
{
if(tmrnbr < NR_OF_TIMERS)
{
time *= TimerForFWUpgrade::timeBase;
singleTimer[tmrnbr]->set(time);
}
}
//static
char TimerForFWUpgrade::isElapsed(unsigned char tmrnbr)
{
if(true == singleTimer[tmrnbr]->isElapsed())
{
return 1;
}
else
{
return 0;
}
}
Module SingleTimer:
SingleTimer::SingleTimer(QObject* parent) : QObject(parent),
pTime(new QTimer(this)),
myElapsed(true)
{
connect(pTime, SIGNAL(timeout()), this, SLOT(slot_setElapsed()));
pTime->setTimerType(Qt::PreciseTimer);
pTime->setSingleShot(true);
}
void SingleTimer::set(unsigned int time)
{
myElapsed = false;
pTime->start(time);
}
bool SingleTimer::isElapsed()
{
QCoreApplication::processEvents();
return myElapsed;
}
void SingleTimer::slot_setElapsed()
{
myElapsed = true;
}
Use QTimer for this purpose and make use of SIGNALS and SLOT for the purpose of starting and stopping the timer/s from different threads. You can emit the signal from any thread and catch it in the thread which created the timer to act on it.
Since you say you are new to Qt, I suggest you go through some tutorials before proceeding so that you will know what Qt has to offer and don't end up trying to reinvent the wheel. :)
VoidRealms is a good starting point.
You have this problem because the timers in the static array is created in Thread X, but started and stopped in Thread Y. This is not allowed, because Qt rely on thread affinity to timeout timers.
You can either create, start stop in the same thread or use signal and slots to trigger start and stop operations for timers. The signal and slot solution is a bit problematic Because you have n QTimer objects (Hint: how do you start the timer at position i?)
What you can do instead is create and initialize the timer at position tmrnbr in
TimerForFWUpgrade::set(unsigned char tmrnbr, unsigned int time)
{
singleTimer[tmrnbr] = new SingleTimer(0);
singleTimer[tmrnbr]->set(time);
}
which is executed by the same thread.
Futhermore, you don't need a SingleTimer class. You are using Qt5, and you already have all you need at your disposal:
SingleTimer::isElapsed is really QTimer::remainingTime() == 0;
SingleTimer::set is really QTimer::setSingleShot(true); QTimer::start(time);
SingleTimer::slot_setElapsed becomes useless
ThusSingleTimer::SingleTimer becomes useless and you dont need a SingleTimer class anymore
I got the errors away after changing my timer concept. I'dont use anymore my SingleTimer module. Before the QTimer I won't let timeout and maybe because of that I run into problems. Now I have a cyclic QTimer that times out every 100ms in slot function I will then count the events. Below my working code:
TimerForFWUpgrade::TimerForFWUpgrade(QObject* parent) : QObject(parent),
pTime(new QTimer(this))
{
connect(pTime, SIGNAL(timeout()), this, SLOT(slot_handleTimer()));
pTime->setTimerType(Qt::PreciseTimer);
pTime->start(100);
}
void TimerForFWUpgrade::set(unsigned char tmrnbr, unsigned int time)
{
if(tmrnbr < NR_OF_TIMERS)
{
if(timeBase != 0)
{
myTimeout[tmrnbr] = time / timeBase;
}
else
{
myTimeout[tmrnbr] = 0;
}
myTimer[tmrnbr] = 0;
myElapsed[tmrnbr] = false;
myActive[tmrnbr] = true;
}
}
char TimerForFWUpgrade::isElapsed(unsigned char tmrnbr)
{
QCoreApplication::processEvents();
if(tmrnbr < NR_OF_TIMERS)
{
if(true == myElapsed[tmrnbr])
{
return 1;
}
else
{
return 0;
}
}
else
{
return 0; // NOK
}
}
void TimerForFWUpgrade::slot_handleTimer()
{
for(UINT8 i = 0; i < NR_OF_TIMERS; i++)
{
if(myActive[i] == true)
{
myTimer[i]++;
if(myTimeout[i] < myTimer[i])
{
myTimer[i] = 0;
myElapsed[i] = true;
myActive[i] = false;
}
}
}
}
Related
I'm using libsourcey which uses libuv as its underlying I/O networking layer.
Everything is setup and seems to run (haven't testen anything yet at all since I'm only prototyping and experimenting). However, I require that next to the application loop (the one that comes with libsourcey which relies on libuv's loop), also calls an "Idle function". As it is now, it calls the Idle CB on every cycle which is very CPU consuming. I'd need a way to limit the call-rate of the uv_idle_cb without blocking the calling thread which is the same the application uses to process I/O data (not sure about this last statement, correct me if i'm mistaken).
The idle function will be managing several different aspects of the application and it needs to run only x times within 1 second. Also, everything needs to run one the same thread (planning to upgrade an older application's network infrastructure which runs entirely single-threaded).
This is the code I have so far which also includes the test I did with sleeping the thread within the callback but it blocks everything so even the 2nd idle cb I set up has the same call-rate as the 1st one.
struct TCPServers
{
CTCPManager<scy::net::SSLSocket> ssl;
};
int counter = 0;
void idle_cb(uv_idle_t *handle)
{
printf("Idle callback %d TID %d\n", counter, std::this_thread::get_id());
counter++;
std::this_thread::sleep_for(std::chrono::milliseconds(1000 / 25));
}
int counter2 = 0;
void idle_cb2(uv_idle_t *handle)
{
printf("Idle callback2 %d TID %d\n", counter2, std::this_thread::get_id());
counter2++;
std::this_thread::sleep_for(std::chrono::milliseconds(1000 / 50));
}
class CApplication : public scy::Application
{
public:
CApplication() : scy::Application(), m_uvIdleCallback(nullptr), m_bUseSSL(false)
{}
void start()
{
run();
if (m_uvIdleCallback)
uv_idle_start(&m_uvIdle, m_uvIdleCallback);
if (m_uvIdleCallback2)
uv_idle_start(&m_uvIdle2, m_uvIdleCallback2);
}
void stop()
{
scy::Application::stop();
uv_idle_stop(&m_uvIdle);
if (m_bUseSSL)
scy::net::SSLManager::instance().shutdown();
}
void bindIdleEvent(uv_idle_cb cb)
{
m_uvIdleCallback = cb;
uv_idle_init(loop, &m_uvIdle);
}
void bindIdleEvent2(uv_idle_cb cb)
{
m_uvIdleCallback2 = cb;
uv_idle_init(loop, &m_uvIdle2);
}
void initSSL(const std::string& privateKeyFile = "", const std::string& certificateFile = "")
{
scy::net::SSLManager::instance().initNoVerifyServer(privateKeyFile, certificateFile);
m_bUseSSL = true;
}
private:
uv_idle_t m_uvIdle;
uv_idle_t m_uvIdle2;
uv_idle_cb m_uvIdleCallback;
uv_idle_cb m_uvIdleCallback2;
bool m_bUseSSL;
};
int main()
{
CApplication app;
app.bindIdleEvent(idle_cb);
app.bindIdleEvent2(idle_cb2);
app.initSSL();
app.start();
TCPServers srvs;
srvs.ssl.start("127.0.0.1", 9000);
app.waitForShutdown([&](void*) {
srvs.ssl.shutdown();
});
app.stop();
system("PAUSE");
return 0;
}
Thanks in advance if anyone can help out.
Solved the problem by using uv_timer_t and uv_timer_cb (Hadn't digged into libuv's doc yet). CPU usage went down drastically and nothing gets blocked.
I've wrote a timer using std::thread - here is how it looks like:
TestbedTimer::TestbedTimer(char type, void* contextObject) :
Timer(type, contextObject) {
this->active = false;
}
TestbedTimer::~TestbedTimer(){
if (this->active) {
this->active = false;
if(this->timer->joinable()){
try {
this->timer->join();
} catch (const std::system_error& e) {
std::cout << "Caught system_error with code " << e.code() <<
" meaning " << e.what() << '\n';
}
}
if(timer != nullptr) {
delete timer;
}
}
}
void TestbedTimer::run(unsigned long timeoutInMicroSeconds){
this->active = true;
timer = new std::thread(&TestbedTimer::sleep, this, timeoutInMicroSeconds);
}
void TestbedTimer::sleep(unsigned long timeoutInMicroSeconds){
unsigned long interval = 500000;
if(timeoutInMicroSeconds < interval){
interval = timeoutInMicroSeconds;
}
while((timeoutInMicroSeconds > 0) && (active == true)){
if (active) {
timeoutInMicroSeconds -= interval;
/// set the sleep time
std::chrono::microseconds duration(interval);
/// set thread to sleep
std::this_thread::sleep_for(duration);
}
}
if (active) {
this->notifyAllListeners();
}
}
void TestbedTimer::interrupt(){
this->active = false;
}
I'm not really happy with that kind of implementation since I let the timer sleep for a short interval and check if the active flag has changed (but I don't know a better solution since you can't interrupt a sleep_for call). However, my program core dumps with the following message:
thread is joinable
Caught system_error with code generic:35 meaning Resource deadlock avoided
thread has rejoined main scope
terminate called without an active exception
Aborted (core dumped)
I've looked up this error and as seems that I have a thread which waits for another thread (the reason for the resource deadlock). However, I want to find out where exactly this happens. I'm using a C library (which uses pthreads) in my C++ code which provides among other features an option to run as a daemon and I'm afraid that this interfers with my std::thread code. What's the best way to debug this?
I've tried to use helgrind, but this hasn't helped very much (it doesn't find any error).
TIA
** EDIT: The code above is actually not exemplary code, but I code I've written for a routing daemon. The routing algorithm is a reactive meaning it starts a route discovery only if it has no routes to a desired destination and does not try to build up a routing table for every host in its network. Every time a route discovery is triggered a timer is started. If the timer expires the daemon is notified and the packet is dropped. Basically, it looks like that:
void Client::startNewRouteDiscovery(Packet* packet) {
AddressPtr destination = packet->getDestination();
...
startRouteDiscoveryTimer(packet);
...
}
void Client::startRouteDiscoveryTimer(const Packet* packet) {
RouteDiscoveryInfo* discoveryInfo = new RouteDiscoveryInfo(packet);
/// create a new timer of a certain type
Timer* timer = getNewTimer(TimerType::ROUTE_DISCOVERY_TIMER, discoveryInfo);
/// pass that class as callback object which is notified if the timer expires (class implements a interface for that)
timer->addTimeoutListener(this);
/// start the timer
timer->run(routeDiscoveryTimeoutInMilliSeconds * 1000);
AddressPtr destination = packet->getDestination();
runningRouteDiscoveries[destination] = timer;
}
If the timer has expired the following method is called.
void Client::timerHasExpired(Timer* responsibleTimer) {
char timerType = responsibleTimer->getType();
switch (timerType) {
...
case TimerType::ROUTE_DISCOVERY_TIMER:
handleExpiredRouteDiscoveryTimer(responsibleTimer);
return;
....
default:
// if this happens its a bug in our code
logError("Could not identify expired timer");
delete responsibleTimer;
}
}
I hope that helps to get a better understanding of what I'm doing. However, I did not to intend to bloat the question with that additional code.
I have started a timer and set the interval as 5 secs and registered a signal handler for it.
When SIGALRM is encountered iam trying to terminate the thread inside the signal handler, bt not able to do that. Thread is not getting terminated , instead of this whole process is killed.
The following is the code:
void signalHandler()
{
printf("Caught signal ...\n");
printf("Now going to terminate thread..\n");
pthread_kill(tid, SIGKILL);
}
void * thread_function()
{
int oldstate;
char result[256] = {0};
time_t startTime = time(NULL);
time_t timerDuration = 5;
time_t endTime = startTime + timerDuration;
while(1) {
printf("Timer is runnuing as dameon..\n");
if(!strcmp(result, "CONNECTED")) {
resp = 1;
pthread_exit(&resp);
}
}
}
int main()
{
int *ptr[2];
signal(SIGALRM, signalHandler);
timer.it_interval.tv_usec = 0;
timer.it_interval. tv_usec = 0;
timer.it_value.tv_sec = INTERVAL;
timer.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &timer, 0);
pthread_create(&tid, NULL, thread_function, NULL);
pthread_join(tid, (void**)&(ptr[0]));
printf("test %d\n\n",*ptr[0]);
while(1)
printf("1");
}
Platform : Linux , gcc compiler
As far as I'm aware you pretty much can't call anything inside a signal handler as you don't know what state your code is in.
Your best option is to set up a thread to handle your signals. All your other threads should call pthread_setsigmask and to block all signals, and then you create another thread, which calls calls pthread_setsigmask to catch SIGALARM, and then calls sigwait, at which point it can cancel the other thread.
The way of handling signals is much different in a multi-threaded environment as compared to a single threaded environment. In a multi-threaded code, you should block out all the signals for all the threads that have your business logic and then create a seperate thread for handling the signals. This is because, in multi-threaded environment, you cannot be sure to which thread the signal will be delivered.
Please refer to this link for more details:
http://devcry.heiho.net/2009/05/pthreads-and-unix-signals.html
Apart from this, to kill a thread use pthread_cancel which should work fine for you.
You can try using a flag:
int go_on[number_of_threads] = { 1 };
void signalHandler()
{
printf("Caught signal ...\n");
printf("Now going to terminate thread..\n");
go_on[tid] = 0;
}
void * thread_function()
{ /* */
while(go_on[this_thread_id]) {
printf("Timer is runnuing as dameon..\n");
if(!strcmp(result, "CONNECTED")) {
resp = 1;
pthread_exit(&resp);
}
}
}
If there is something more difficult than debugging a multithreaded app that is trying to describe the bug itself.
I have two boost::threads (application and display).
Both use the same asio::io_service to do their work.
The display thread has a std::set of type window* which is a class I use to wrap winapi window management.
I use a custom message queue to communicate these two threads.
One of these messages (terminate) is used to notify the display thread that it must not "post" any more methods and that it must call thread_group.remove_thread and remove itself.
The thread has a variable (state) that flags the state of the thread (running, paused, terminated).
If it is running it "posts" it's update() method that iterates an std::set and calls the update method in each window* it contains.
If it is terminated, it clears the std::set, removes itself from the thread_group and doesn't post any more work.
The problem: Once a while, when trying to close the app, the thread's update method gets ran after the thread got "terminated" and the std::set got cleared. Then the update method tries to iterate the std::set and a SIGSEGV takes place. This only happens 1 every 10 runs of the application and I'm having a hard time trying to guess what's wrong.
I'll try to post the relevant code, if more is needed I'll try to add it.
int main(int argc, char **argv)
{
boost::asio::io_service ios;
boost::asio::strand strand(ios);
boost::thread_group threads;
owl::system::pump pump;
application app(&threads, &strand, &pump);
owl::system::display display(&strand, &pump);
ios.run();
threads.join_all();
return 0;
}
...
void display::on_terminate()
{
close_all_windows();
}
...
void display::close_all_windows()
{
windows.move_first();
while (!windows.eof())
{
window* win = windows.value();
win->destroy();
delete win;
windows.move_next();
}
windows.clear();
check_no_window();
}
...
void display::on_update()
{
if (windows.size())
{
windows.move_first();
while (!windows.eof())
{
windows.value()->update();
windows.move_next(); // Here happens the SIGSEGV
}
}
}
The class display inherits the class subsystem that manages thread execution. This is the relevant code involving the execution of on_update()
void subsystem::do_update()
{
message* msg;
size_t message_count = messages.size();
for (size_t i=0; i<message_count; i++)
{
msg = messages[i];
process_message(msg);
strand->dispatch(strand->wrap(boost::bind(&message::deallocate, msg)));
}
switch (state)
{
case running:
{
on_update();
}
break;
case paused:
{
// Do not update. Just check the queue and sleep
sleep(10);
}
break;
case terminated:
{
do_terminate();
return;
}
break;
}
strand->post(strand->wrap(boost::bind(&subsystem::check_for_messages, this)));
}
void subsystem::check_for_messages()
{
messages.clear();
pump->get_messages(this, messages);
ios->post(boost::bind(&subsystem::do_update, this));
}
The SIGSEGV occurs exactly when trying to increment the std::set iterator.
Child process PID: 2272
Program received signal SIGSEGV, Segmentation fault.
In std::_Rb_tree_increment(std::_Rb_tree_node_base const*) ()
stl_tree.h:269
I've a for loop that will launch processes in parallel every launched process will return a response back indicating that it is ready. I want to wait for the response and I'll abort if a certain timeout is reached.
Development environment is VS2008
Here is the pseudo code:
void executeCommands(std::vector<Command*> commands)
{
#pragma omp parallel for
for (int i = 0; i < commands.size(); i++)
{
Command* cmd = commands[i];
DWORD pid = ProcessLauncher::launchProcess(cmd->getWorkingDirectory(), cmd->getCommandToExcecute(), cmd->params);
//Should I wait for process to become ready?
if (cmd->getWaitStatusTimeout() > 0)
{
ProcessStatusManager::getInstance().addListener(*this);
//TODO: emit process launching signal
//BEGINNING OF QUESTION
//I don't how to do this part.
//I might use QT's QWaitCondition but if there is another solution in omp
//I'd like to use it
bool timedOut;
SOMEHANDLE handle = Openmp::waitWithTimeout(cmd->getWaitStatusTimeout(), &timedOut);
mWaitConditions[pid]) = handle;
//END OF QUESTION
if (timedOut)
{
ProcessStatusManager::getInstance().removeListener(*this);
//TODO: kill process
//TODO: emit fail signal
}
else
{
//TODO: emit process ready signal
}
}
else
{
//TODO: emit process ready signal
}
}
}
void onProcessReady(DWORD sourceProcessPid)
{
ProcessStatusManager::getInstance().removeListener(*this);
SOMEHANDLE handle = mWaitConditions[sourceProcessPid];
if (mWaitConditions[sourceProcessPid] != 0)
{
Openmp::wakeAll(handle);
}
}
As the comment above pointed out, Michael Suess did present a paper on adding this functionality to OpenMP. He is the last of several people that have proposed adding some type of wait function to OpenMP. The OpenMP language committee has taken the issue up several times. Each time it has been rejected because there are other ways to do this function already. I don't know Qt, but as long as the functions it provides are thread safe, then you should be able to use them.