How to stop g_main_loop_run properly? - c++

I am using GLib for the first time. So, to understand how to use GLib APIs, I wrote following dummy program.
#include<glib.h>
#include<iostream>
#include<thread>
#include<chrono>
using namespace std;
using namespace std::chrono_literals;
class executor
{
private:
GMainLoop* main_loop;
GMainContext* worker_context;
thread worker_thread;
void worker_loop()
{
g_main_context_push_thread_default(worker_context);
cout << "Starting main loop" << endl;
g_main_loop_run(main_loop);
cout << "Finished main loop" << endl;
g_main_context_pop_thread_default(worker_context);
}
public:
executor()
{
worker_context = g_main_context_new();
main_loop = g_main_loop_new(worker_context, false);
worker_thread = thread(&executor::worker_loop, this);
}
~executor()
{
g_main_loop_quit(main_loop);
cout << "Stopped main loop from running" << endl;
g_main_loop_unref(main_loop);
g_main_context_unref(worker_context);
if (worker_thread.joinable())
{
worker_thread.join();
}
}
void queue_callback(int (*callback)(void))
{
GSource* idle_source = g_idle_source_new();
g_source_set_callback(idle_source, (GSourceFunc)callback, NULL, NULL);
g_source_attach(idle_source, worker_context);
g_source_unref(idle_source);
}
};
int func1()
{
cout << "func1 started" << endl;
this_thread::sleep_for(5s);
cout << "func1 finished waiting" << endl;
return 0;
}
int func2()
{
cout << "func2 started" << endl;
this_thread::sleep_for(1s);
cout << "func2 finished waiting" << endl;
return 0;
}
int main()
{
executor e;
e.queue_callback(func1);
e.queue_callback(func2);
return 0;
}
When I run the program, it does not finish executing, it gets stuck. This is the output it prints.
Stopped main loop from running
Starting main loop
func1 started
func1 finished waiting
func2 started
func2 finished waiting
Sometimes it just fails with following error
Stopped main loop from running
Starting main loop
(process:16343): GLib-CRITICAL **: 10:58:54.405: g_main_loop_run: assertion 'g_atomic_int_get (&loop->ref_count) > 0' failed
Finished main loop
My guess is these both problems are happening because g_main_loop_quit and g_main_loop_unref run before g_main_loop_run. How do I fix these issues?
EDIT after user7860670's comment:
Thanks to user7860670 for the suggestion. Here is the working code now.
#include<glib.h>
#include<iostream>
#include<thread>
#include<chrono>
using namespace std;
using namespace std::chrono_literals;
class executor
{
private:
GMainLoop* main_loop;
GMainContext* worker_context;
thread worker_thread;
void worker_loop()
{
g_main_context_push_thread_default(worker_context);
cout << "Starting main loop" << endl;
g_main_loop_run(main_loop);
cout << "Finished main loop" << endl;
g_main_context_pop_thread_default(worker_context);
}
public:
executor()
{
worker_context = g_main_context_new();
main_loop = g_main_loop_new(worker_context, false);
worker_thread = thread(&executor::worker_loop, this);
}
~executor()
{
cout << "Stopping main loop" << endl;
GSource* idle_source = g_idle_source_new();
g_source_set_callback(idle_source, (GSourceFunc)g_main_loop_quit, main_loop, NULL);
g_source_attach(idle_source, worker_context);
g_source_unref(idle_source);
if (worker_thread.joinable())
{
worker_thread.join();
}
cout << "Removing references to main loop and context" << endl;
g_main_loop_unref(main_loop);
g_main_context_unref(worker_context);
}
void queue_callback(int (*callback)(void))
{
GSource* idle_source = g_idle_source_new();
g_source_set_callback(idle_source, (GSourceFunc)callback, NULL, NULL);
g_source_attach(idle_source, worker_context);
g_source_unref(idle_source);
}
};
int func1()
{
cout << "func1 started" << endl;
this_thread::sleep_for(5s);
cout << "func1 finished waiting" << endl;
return 0;
}
int func2()
{
cout << "func2 started" << endl;
this_thread::sleep_for(1s);
cout << "func2 finished waiting" << endl;
return 0;
}
int main()
{
executor e;
e.queue_callback(func1);
e.queue_callback(func2);
return 0;
}

It looks like executor e; may go out of scope prior to worker thread starting to work and since at the ~executor() you are unrefing loop and context objects prior to waiting for worker thread their reference count drops to 0 and they are getting destroyed prior to working thread working. You should do it other way around: wait for a worker thread to finish and only then unref loop and context objects.

Related

Use pthread_cancel in QNX system has a memory leak, but it does not exist on the Linux system

I have a code, main thread create 2 thread(thread_1 and thread_2), I use pthread_cancel to cancel thread_1 in thread_2, but the data that I create in thread_1 will not be destructored when I run it in QNX system, but there is no problem in Linux system.
It my test code, when I run it in QNX system,MyClass and MyClass2 object destructor not be called, so the 100M memory will leak; but run it in Linux system,it will call MyClass and MyClass2 object destructor. why is there such a difference???
#include <iostream>
#include <pthread.h>
#include <thread>
using namespace std;
pthread_t thread_id_1;
pthread_t thread_id_2;
class MyClass2
{
public:
MyClass2() {
cout << "Build MyClass2" << endl;
}
~MyClass2() {
cout << "Destory MyClass2" << endl;
}
};
class MyClass
{
public:
MyClass() {
cout << "Build MyClass" << endl;
p = (char *)malloc(1024 * 1024 *100);
}
~MyClass() {
cout << "Destory MyClass" << endl;
free(p);
}
char *p;
};
void func(int i)
{
MyClass2 c2;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
cout << "thread 1 func:" << i << endl;
}
static void *thread_1(void *arg)
{
MyClass my_class;
int type_value = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
cout << "thread_1 set cancle type+++++:" << type_value << endl;
for (int i = 0; i < 10; i++) {
func(i);
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
return nullptr;
}
static void *thread_2(void *arg)
{
for (int i = 0; i < 10; i++) {
cout << "thread_2:" << i << endl;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
int ret = pthread_cancel(thread_id_1);
cout << "otx_thread_2 cancel thread 1 ret:" << ret << endl;
return nullptr;
}
int main(int argc, char *argv[])
{
cout << "Main start" << endl;
pthread_attr_t attr;
pthread_attr_init( &attr );
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
cout << "Main set detch" << endl;
if (pthread_create(&thread_id_1, &attr, thread_1, nullptr) != 0) {
cout << "pthread_create() 1 error" << endl;
return -1;
}
if (pthread_create(&thread_id_2, nullptr, thread_2, nullptr) != 0) {
cout << "pthread_create() 2 error" << endl;
return -1;
}
if (pthread_join(thread_id_2, NULL) != 0) {
cout << "pthread_join() 1 error";
return -1;
}
while (1) {
cout << "Main Loop" << endl;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
return 0;
}
enter image description here
enter image description here
I try it again and again, so I confirm that there is no problem with the code, But I don't understand why there is such a difference
pthread_cancel is outside the scope of the C++ specification. C++ does not specify its behavior, nor inherit it from C or POSIX.
The difference is simply because QNX and Linux have implemented pthread_cancel differently in a C++ environment. There is literally nothing more to it than that.
I imagine that the QNX implementation stops the thread in its tracks, whereas the Linux implementation probably induces an exception which unwinds the canceled thread's stack.

How do I pass member functions to g_source_set_callback?

I am trying to pass member function pointers to g_source_set_callback to queue them. This is a dummy code that I wrote.
#include<glib.h>
#include<iostream>
#include<thread>
#include<chrono>
using namespace std;
using namespace std::chrono_literals;
class executor
{
private:
GMainLoop* main_loop;
GMainContext* worker_context;
thread worker_thread;
void worker_loop()
{
g_main_context_push_thread_default(worker_context);
cout << "Starting main loop" << endl;
g_main_loop_run(main_loop);
cout << "Finished main loop" << endl;
g_main_context_pop_thread_default(worker_context);
}
void queue_callback(int (*callback)(void))
{
GSource* idle_source = g_idle_source_new();
g_source_set_callback(idle_source, (GSourceFunc)callback, NULL, NULL);
g_source_attach(idle_source, worker_context);
g_source_unref(idle_source);
}
int func1()
{
cout << "func1 started" << endl;
this_thread::sleep_for(5s);
cout << "func1 finished waiting" << endl;
return 0;
}
int func2()
{
cout << "func2 started" << endl;
this_thread::sleep_for(1s);
cout << "func2 finished waiting" << endl;
return 0;
}
public:
executor()
{
worker_context = g_main_context_new();
main_loop = g_main_loop_new(worker_context, false);
worker_thread = thread(&executor::worker_loop, this);
}
~executor()
{
cout << "Stopping main loop" << endl;
GSource* idle_source = g_idle_source_new();
g_source_set_callback(idle_source, (GSourceFunc)g_main_loop_quit, main_loop, NULL);
g_source_attach(idle_source, worker_context);
g_source_unref(idle_source);
if (worker_thread.joinable())
{
worker_thread.join();
}
cout << "Removing references to main loop and context" << endl;
g_main_loop_unref(main_loop);
g_main_context_unref(worker_context);
}
void start()
{
queue_callback(func1);
queue_callback(func2);
}
};
int main()
{
executor e;
e.start();
return 0;
}
I know that you cannot pass non-static member function like that, so, I get following compilation error as expected.
test.cpp: In member function ‘void executor::start()’:
test.cpp:79:37: error: invalid use of non-static member function ‘int executor::func1()’
queue_callback(func1);
^
test.cpp:35:13: note: declared here
int func1()
^~~~~
test.cpp:80:37: error: invalid use of non-static member function ‘int executor::func2()’
queue_callback(func2);
^
test.cpp:43:13: note: declared here
int func2()
^~~~~
I saw someone using function objects to wrap the member functions. So, I tried this.
#include<glib.h>
#include<iostream>
#include<thread>
#include<chrono>
#include<functional>
using namespace std;
using namespace std::chrono_literals;
class executor
{
private:
GMainLoop* main_loop;
GMainContext* worker_context;
thread worker_thread;
void worker_loop()
{
g_main_context_push_thread_default(worker_context);
cout << "Starting main loop" << endl;
g_main_loop_run(main_loop);
cout << "Finished main loop" << endl;
g_main_context_pop_thread_default(worker_context);
}
void queue_callback(const function<int()>* callback)
{
GSource* idle_source = g_idle_source_new();
g_source_set_callback(idle_source, reinterpret_cast<GSourceFunc>(&on_callback), const_cast<function<int()>*>(callback), NULL);
g_source_attach(idle_source, worker_context);
g_source_unref(idle_source);
}
static int on_callback(const function<int()>* callback)
{
return (*callback)();
}
int func1()
{
cout << "func1 started" << endl;
this_thread::sleep_for(5s);
cout << "func1 finished waiting" << endl;
return 0;
}
int func2()
{
cout << "func2 started" << endl;
this_thread::sleep_for(1s);
cout << "func2 finished waiting" << endl;
return 0;
}
public:
executor()
{
worker_context = g_main_context_new();
main_loop = g_main_loop_new(worker_context, false);
worker_thread = thread(&executor::worker_loop, this);
}
~executor()
{
cout << "Stopping main loop" << endl;
GSource* idle_source = g_idle_source_new();
g_source_set_callback(idle_source, (GSourceFunc)g_main_loop_quit, main_loop, NULL);
g_source_attach(idle_source, worker_context);
g_source_unref(idle_source);
if (worker_thread.joinable())
{
worker_thread.join();
}
cout << "Removing references to main loop and context" << endl;
g_main_loop_unref(main_loop);
g_main_context_unref(worker_context);
}
void start()
{
cout << "Submitting func1 callback" << endl;
function<int()> callback1 = [this]() {
return func1();
};
queue_callback(&callback1);
cout << "Submitting func2 callback" << endl;
function<int()> callback2 = [this]() {
return func2();
};
queue_callback(&callback2);
}
};
int main()
{
executor e;
e.start();
return 0;
}
This code compiles, but I keep getting either segmentation fault or bad_function_call exception.
Starting main loop
Submitting func1 callback
Submitting func2 callback
Stopping main loop
func1 started
func1 finished waiting
terminate called after throwing an instance of 'std::bad_function_call'
what(): bad_function_call
Aborted (core dumped)
I think I am getting error because callback1 and callback2 are local objects and by the time they are executed, memory for them is freed.
How do I fix this? I thought of using unique_ptrs, but couldn't figure out how as g_source_set_callback takes int (*GSourceFunc) void as second argument and void* as third.
I figured it out.
I create a new std::function object and pass it to g_source_set_callback. When on_callback is called, I typecast the void * to std::function<int()>*, call it and delete it.
Here is the working code.
#include<glib.h>
#include<iostream>
#include<thread>
#include<chrono>
#include<functional>
using namespace std;
using namespace std::chrono_literals;
class executor
{
private:
GMainLoop* main_loop;
GMainContext* worker_context;
thread worker_thread;
void worker_loop()
{
g_main_context_push_thread_default(worker_context);
cout << "Starting main loop" << endl;
g_main_loop_run(main_loop);
cout << "Finished main loop" << endl;
g_main_context_pop_thread_default(worker_context);
}
void queue_callback(function<int()>&& callback)
{
GSource* idle_source = g_idle_source_new();
g_source_set_callback(idle_source, on_callback, new function<int()>(callback), NULL);
g_source_attach(idle_source, worker_context);
g_source_unref(idle_source);
}
static int on_callback(void* ptr)
{
function<int()>* callback = static_cast<function<int()>*>(ptr);
int ret = (*callback)();
delete callback;
return ret;
}
int func1()
{
cout << "func1 started" << endl;
this_thread::sleep_for(5s);
cout << "func1 finished waiting" << endl;
return 0;
}
int func2()
{
cout << "func2 started" << endl;
this_thread::sleep_for(1s);
cout << "func2 finished waiting" << endl;
return 0;
}
public:
executor()
{
worker_context = g_main_context_new();
main_loop = g_main_loop_new(worker_context, false);
worker_thread = thread(&executor::worker_loop, this);
}
~executor()
{
cout << "Stopping main loop" << endl;
GSource* idle_source = g_idle_source_new();
g_source_set_callback(idle_source, (GSourceFunc)g_main_loop_quit, main_loop, NULL);
g_source_attach(idle_source, worker_context);
g_source_unref(idle_source);
if (worker_thread.joinable())
{
worker_thread.join();
}
cout << "Removing references to main loop and context" << endl;
g_main_loop_unref(main_loop);
g_main_context_unref(worker_context);
}
void start()
{
cout << "Submitting func1 callback" << endl;
queue_callback([this]() { return func1(); });
cout << "Submitting func2 callback" << endl;
queue_callback([this]() { return func2(); });
}
};
int main()
{
executor e;
e.start();
return 0;
}

How to initialized pthread_t variable in class constructor

How to initialized pthread_t variable in class constructor.
C++ Static Analysis(coverity) Error: Non-static class member threadId is not initialized in this constructor nor in any functions that it calls.
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
void *
threadFunc(void * arg)
{
std::cout << "Thread Function :: Start" << std::endl;
// Sleep for 2 seconds
sleep(2);
std::cout << "Thread Function :: End" << std::endl;
return NULL;
}
class threads
{
private:
pthread_t threadId;
int err;
public:
threads():err(0){};
~threads(){};
void create_thread();
void join_thread();
};
void
threads::create_thread()
{
// Create a thread that will function threadFunc()
err = pthread_create(&threadId, NULL, &threadFunc, NULL);
// Check if thread is created sucessfuly
if (err)
{
std::cout << "Thread creation failed : " << strerror(err);
}
else
{
std::cout << "Thread Created with ID : " << threadId << std::endl;
}
}
void
threads::join_thread()
{
err = pthread_join(threadId, NULL);
// check if joining is sucessful
if (err)
{
std::cout << "Failed to join Thread : " << strerror(err) << std::endl;
}
}
int main()
{
threads T;
T.create_thread();
T.join_thread();
std::cout << "Exiting Main" << std::endl;
return 0;
}
Note:
I have checked all existing questions and answer in Stackoverflow.
But none of them have clear answer.
The above c++ code is a sample code(copied from Internet and updated to show my actual problem)
I have tried this and its working (Posting the answer, to help others)
#include <iostream>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
void *
threadFunc(void * arg)
{
std::cout << "Thread Function :: Start" << std::endl;
// Sleep for 2 seconds
sleep(2);
std::cout << "Thread Function :: End" << std::endl;
return NULL;
}
class threads
{
private:
pthread_t threadId;
int err;
public:
threads():err(0){ threadId = pthread_t(); std::cout <<threadId<<std::endl;};
~threads(){};
void create_thread();
void join_thread();
};
void
threads::create_thread()
{
// Create a thread that will function threadFunc()
err = pthread_create(&threadId, NULL, &threadFunc, NULL);
// Check if thread is created sucessfuly
if (err)
{
std::cout << "Thread creation failed : " << strerror(err);
}
else
{
std::cout << "Thread Created with ID : " << threadId << std::endl;
}
}
void
threads::join_thread()
{
err = pthread_join(threadId, NULL);
// check if joining is sucessful
if (err)
{
std::cout << "Failed to join Thread : " << strerror(err) << std::endl;
}
}
int main()
{
threads T;
T.create_thread();
T.join_thread();
std::cout << "Exiting Main" << std::endl;
return 0;
}

Simple timer mechanism with boost - Issue [Re-rum of run mechanism does not respond with handler message]

Am very much new to C++ and boost library
i have constructed a simple timer mechanism
my issue :
On the first timer run call timer.StartAppTimer(1,10); i am getting the handler message
but when i re-run the start timeer again it says started but after 10 seconds i don't receive no handler message..
Please guide
Below is my code:
#include <iostream>
#include <windows.h>
#include <timer.h>
#define sleep(n) Sleep(1000 * n)
using namespace boost::posix_time;
using namespace std;
void handler1(int id,const boost::system::error_code &ec)
{
if (ec == boost::asio::error::operation_aborted)
{
std::cout << microsec_clock::local_time() << " Handler1: Timer 1 was cancelled or retriggered." << std::endl;
std::cout << "TIMER ID : " << id<< std::endl;
}
else
{
std::cout << microsec_clock::local_time() << " Handler1: expired." << std::endl;
std::cout << "fsm RECIEVE msgBuf : " << id<< std::endl;
}
}
Mytimer::Mytimer()
: m_pTimer(NULL),
m_pThread(NULL)
{
m_pTimer = new boost::asio::deadline_timer(io_service1);
}
void Mytimer::runTimerThread()
{
std::cout << "IO Service started " << std::endl;
io_service1.run();
}
void Mytimer::startTimer(int time,int timerId)
{
m_pTimer->expires_from_now(boost::posix_time::seconds(time));
m_pTimer->async_wait(boost::bind(handler1,timerId,boost::asio::placeholders::error));
m_pThread = new boost::thread(&Mytimer::runTimerThread, this);
}
void Mytimer::stopTimer()
{
io_service1.reset();
io_service1.stop();
}
bool Mytimer::isRunning()
{
time_duration td = m_pTimer->expires_from_now();
if (td.total_seconds() > 0)
{
return true;
}
return false;
}
void TimerAccess::StartAppTimer(int Timerid,int TimerPeriod){
std::cout << "TIMER ID : " << Timerid<< std::endl;
if (Timerid == APPTIMER1){
timer1.startTimer(TimerPeriod,Timerid);
}
if (Timerid == APPTIMER2){
timer2.startTimer(TimerPeriod,Timerid);
}
if (Timerid == APPTIMER3){
timer3.startTimer(TimerPeriod,Timerid);
}
}
void TimerAccess::StopTimer(int Timerid){
if (Timerid == APPTIMER1){
timer1.stopTimer();
}
if (Timerid == APPTIMER2){
timer2.stopTimer();
}
if (Timerid == APPTIMER3){
timer3.stopTimer();
}
// return -1;
}
int main()
{
cout << " before timer construction" << endl;
TimerAccess timer;
timer.StartAppTimer(1,10);
sleep(15);
cout << " before starting timer 2" << endl;
timer.StartAppTimer(1,10);
sleep(30);
cout << " END OF MAIN " << endl;
}

Visual C++ Threads Simple Example

I am trying to create a basic thread from main by passing a function to _beginthread.
But My output is not getting completed.
I am getting the following output:
Starting thread
48
Main ends
I
Could someone please clarify what is wrong in the following code?
#include <iostream>
#include <process.h>
using namespace std;
void test(void *param)
{
cout << "In thread function" << endl;
Sleep(1000); // sleep for 1 second
cout << "Thread function ends" << endl;
_endthread();
}
int main()
{
cout << "Starting thread" << endl;
cout << _beginthread(test,0,NULL);
cout << "Main ends" << endl;
return 0;
}
Because return from the main will stop any threads in your application. You need to wait untill thread will stop. Simplest solution with global var - very bad example to be honest. You need to use wait functions on thread's handle.
#include <iostream>
#include <process.h>
using namespace std;
bool threadFinished = false;
void test(void *param)
{
cout << "In thread function" << endl;
Sleep(1000); // sleep for 1 second
cout << "Thread function ends" << endl;
threadFinished = true;
_endthread();
}
int main()
{
cout << "Starting thread" << endl;
cout << _beginthread(test,0,NULL);
while(!threadFinished)
{
Sleep(10);
}
cout << "Main ends" << endl;
return 0;
}
How to use Wait functions:
HANDLE hThread;
hThread = (HANDLE)_beginthread( test, 0, NULL);
WaitForSingleObject( hThread, INFINITE );
You can use CreateThread method.
Simple example of multithreading.
#include <Windows.h>
#include <iostream>
using namespace std;
DWORD WINAPI thread1(__in LPVOID lpParameter) {
while (1) {
std::cout << " From Thread 1 \n";
Sleep(3000);
}
}
DWORD WINAPI thread2(__in LPVOID lpParameter) {
while (1) {
std::cout << " From thread 2\n";
Sleep(1000);
}
}
int main()
{
DWORD threadID1, threadID2;
HANDLE h1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)thread1, 0, 0,&threadID1);
HANDLE h2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)thread2, 0, 0, &threadID2);
getchar();
return 0;
}
where thread 1 prints for every 3 secs and thread2 prints for every sec.
You can allocate stack size if your process is bigger.
StackSize explanation
You need to wait for thread to end using some synchronization primitives, or your program will call ExitProcess before thread finished his execution.
You may read about synchronization first to understand how to write multithreaded application.In your case you need single object wait functions.
See msdn example: http://msdn.microsoft.com/en-us/library/kdzttdcb%28v=vs.71%29.aspx
so, you main function should look something like this :
int main()
{
HANDLE hThread;
cout << "Starting thread" << endl;
cout << (hThread = (HANDLE)_beginthread(test,0,NULL));
WaitForSingleObject( hThread, INFINITE );
cout << "Main ends" << endl;
return 0;
}