I am struggling with calling a clutter function from an extra thread.
I use boost::thread for threading and the clutter library 1.0.
To be specific, the thread contains a looped function that emits boost::signals2::signal with parameters of x and y coordinates every once in a while.
That signal is connected to a function that hands those variables to clutter, i.e. x,y in
clutter_stage_get_actor_at_pos(CLUTTER_STAGE(actor),
CLUTTER_PICK_ALL, x, y);
And that is where i get a segfault.
Apparently clutter has some thread-handling routines. I tried calling
g_thread_init(NULL);
clutter_threads_init();
before starting clutter_main(). I also tried enclosing the clutter function in
clutter_threads_enter();
clutter_stage_get_actor_at_pos(CLUTTER_STAGE(actor),
CLUTTER_PICK_ALL, x, y);
clutter_threads_leave();
but that does also not do the trick..
Every hint is appreciated, thank you in advance!
Addendum
I just forged a minimal sample of what I am trying to do. I already 'protected' the clutter_main() routine as suggested. Some functions of clutter seem to work (e.g setting stage color or setting actor position) from the seperate thread. Is there still something wrong with my code?
#include <clutter/clutter.h>
#include <boost/thread.hpp>
ClutterActor *stage;
ClutterActor* rect = NULL;
void receive_loop()
{
while(1)
{
sleep(1);
clutter_threads_enter();
ClutterActor* clicked = clutter_stage_get_actor_at_pos(CLUTTER_STAGE(stage), CLUTTER_PICK_ALL,300, 500);
clutter_threads_leave();
}
}
int main(int argc, char *argv[])
{
clutter_init(&argc, &argv);
g_thread_init(NULL);
clutter_threads_init();
stage = clutter_stage_get_default();
clutter_actor_set_size(stage, 800, 600);
rect = clutter_rectangle_new();
clutter_actor_set_size(rect, 256, 128);
clutter_actor_set_position(rect, 300, 500);
clutter_group_add (CLUTTER_GROUP (stage), rect);
clutter_actor_show(stage);
boost::thread thread = boost::thread(&receive_loop);
clutter_threads_enter();
clutter_main();
clutter_threads_leave();
return 0;
}
Well, I think I found the answer..
Clutter Docs Gerneral
It says in section "threading model":
The only safe and portable way to use the Clutter API in a multi-threaded environment is to never access the API from a thread that did not call clutter_init() and clutter_main().
The common pattern for using threads with Clutter is to use worker threads to perform blocking operations and then install idle or timeour sources with the result when the thread finished.
Clutter provides thread-aware variants of g_idle_add() and g_timeout_add() that acquire the Clutter lock before invoking the provided callback: clutter_threads_add_idle() and clutter_threads_add_timeout().
So my correction to the minimal sample code would be to alter the receive_loop() to
void receive_loop()
{
while(1)
{
sleep(1);
int pos[2];
pos[0] = 400;
pos[1] = 200;
clutter_threads_add_idle_full (G_PRIORITY_HIGH_IDLE,
get_actor,
&pos,
NULL);
}
}
and to add the get_actor function (as in the example code on the menitioned doc page)
static gboolean
get_actor (gpointer data)
{
int* pos = (int*) data;
ClutterActor* clicked = clutter_stage_get_actor_at_pos(CLUTTER_STAGE(stage), CLUTTER_PICK_ALL, pos[0], pos[1]);
return FALSE;
}
clutter_threads_add_idle_full takes care of thread lock etc..
I struggled with a very similar situation in the Python bindings for clutter. I was never able to make the Clutter thread support work the way I wanted.
What finally did the trick was using an idle proc (gobject.idle_add in python) to push the work I needed done into the main clutter thread. That way I have only 1 thread making clutter calls and everything is fine.
I played with your code and it seems you are doing everything ok, though I'm no expert in Clutter. I also ran your program under gdb and some interesting things showed up:
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb799db70 (LWP 3023)]
0x002d97c6 in glDisable () from /usr/lib/nvidia-current/libGL.so.1
(gdb) thread apply all bt
Thread 2 (Thread 0xb799db70 (LWP 3023)):
#0 0x002d97c6 in glDisable () from /usr/lib/nvidia-current/libGL.so.1
#1 0x001b3ec3 in cogl_disable_fog () from /usr/lib/libclutter-glx-1.0.so.0
#2 0x0018b00a in ?? () from /usr/lib/libclutter-glx-1.0.so.0
#3 0x0019dc82 in clutter_stage_get_actor_at_pos () from /usr/lib/libclutter-glx-1.0.so.0
#4 0x080498de in receive_loop () at seg.cpp:19
Apparently the crash happened on glDisable () from /usr/lib/nvidia-current/libGL.so.1. Notice that I use NVIDIA's OpenGL driver on my GeForce 8600 GT.
Can you confirm that your application also crashes on computers with other video cards (not NVIDIA)? I doubt the crash is due to a bug on NVIDIA's OpenGL implementation.
For me it seems that *clutter_threads_enter/leave()* is not protecting *clutter_stage_get_actor_at_pos()* since I tested *receive_loop()* being called as a callback:
g_signal_connect(stage, "button-press-event", G_CALLBACK(receive_loop), NULL);
so we know that your code seems to be ok.
I encourage you to send your question to Clutter discussion and help mailing list: clutter-app-devel-list
a mailing list for application developers using Clutter, its integration libraries or toolkits based on Clutter.
You can either use clutter_threads_add_idle to update ClutterActor or you need to fix the clutter_threads_enter/leave to switch OpenGL context as well so that you can use it inside a thread.
The crash
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb799db70 (LWP 3023)]
0x002d97c6 in glDisable () from /usr/lib/nvidia-current/libGL.so.1
(gdb) thread apply all bt
Thread 2 (Thread 0xb799db70 (LWP 3023)):
#0 0x002d97c6 in glDisable () from /usr/lib/nvidia-current/libGL.so.1
#1 0x001b3ec3 in cogl_disable_fog () from /usr/lib/libclutter-glx-1.0.so.0
#2 0x0018b00a in ?? () from /usr/lib/libclutter-glx-1.0.so.0
#3 0x0019dc82 in clutter_stage_get_actor_at_pos () from /usr/lib/libclutter-glx-1.0.so.0
#4 0x080498de in receive_loop () at seg.cpp:19
is because the calling thread didn't acquire OpenGL context so it crashed.
Related
Big edit: I think the question can be simplified to--how can I run corebluetooth and initialize CBCentralManager in background thread? Thank you!
I am making an an objective c++ application with CoreBluetooth that runs through the commandline, so the object C portion needs the runloop to be explicitly called [see this]. CoreBluetooth requires there to be an active runloop so callbacks are performed. The code below makes a call to the runloop in the beginning of the program to make everything work:
implementation.mm
// inside init method
// initialize bluetooth manager, must initialize before the runloop
self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
// start run loop
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
while(([runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]))
{}
and I can make async calls from my c++ main method:
main.cpp
int main() {
std::thread worker(do_cpp_things); // c++ things in background thread
run_objective_c_code(); // call objective c code using main thread
}
However with this approach, my c++ portion must be run in the background thread. and the objective C application is in the main thread which is opposite to what I want. So I tried to make a new thread in the objective C file then call the current run loop of the thread:
implementation.mm
// start a new thread
-(void)startThread {
NSThread *A = [[NSThread alloc] initWithTarget:self selector:#selector(runTheLoop) object:nil]; //create thread A
[A start];
}
// call runloop while in new thread
-(void) runTheLoop {
// Commenting out initialization for the sake of simplicity before it terminates when trying to initialize the manager in this example
// self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
// TERMINATES HERE
while(([runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]))
{}
}
But this just terminates early. Not sure if there is something fundamentally wrong with my approach. Again--I want to run my objective-C code in the background thread with an active runloop and my c++ code in the main thread.
Thanks!
Actually wait, this solution doesn't properly make a runloop in background thread:
One of my problems is getting a runloop to run in a background thread.
main.cpp
int main() {
std::thread worker(run_cpp_in_thread);
}
implementation.mm
// somewhere in init method
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop run];
Now the problem is that CoreBluetooth is exiting immediately after powered on the central manager. Seems like something to do with the framework and threading.
I believe you are asking c++ to run in thread which is working in background.
Instead, just push C function to run in background
int main() {
std::thread worker(run_objective c function); // objective c in background thread
do_cpp_things; // call c++ things code using main thread
}
You still need to handle join properly otherwise can make your application unresponsive/crash
The code below throws a segmentation fault inside the .join() of the std::thread class. However, that is happen only I use cv::fastMalloc to allocate a data array. If I use the 'new' keyword or the std::malloc function no error happens.
I need understand why this error happens because in fact I need a cv::Mat that uses this function.
int main() {
uchar* data = (uchar*) cv::fastMalloc(640);
std::atomic<bool> running(true);
std::thread thread([&] () {
while(running) {
// I'll perform some process with data here
// for now, just to illustrate, I put thread to sleep
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
});
std::this_thread::sleep_for(std::chrono::seconds(1));
running = false;
// segfault is thrown here
thread.join();
cv::fastFree(data);
return 0;
}
The GDB callstack follows below
#0 00429B26 _pthread_cleanup_dest () (??:??)
#1 003E32A0 ?? () (??:??)
Does anyone know what might be happening? I really think it is too crazy :S.
Thanks.
I solved this issue reinstalling the opencv. Apparently the problem was the different versions of compilers that I had compiled the opencv and I'm using in this example.
For the record, I had compiled the opencv some time ago with a MinGW version that not support std::thread (I think 4.7.x).
#include < iostream >
#include < pthread.h >
using namespace std;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void* Func(void *)
{
pthread_mutex_lock(&mutex);
cout << "First thread execution" << endl;
pthread_mutex_unlock(&mutex);
}
int main()
{
pthread_t th1;
pthread_create(&th1, NULL, Func, NULL);
pthread_mutex_lock(&mutex);
cout << "In main thread" << endl;
pthread_mutex_lock(&mutex);
// pthread_join(th1, NULL); // Note this code is commented
return 0;
}
I have executed following program on linux fedora 22 (also on http://www.cpp.sh/) around 20 times, and out of 20 execution I have found following outputs:-
Output1:
In main thread
First thread execution
Output2:
First thread execution
In main thread
Output3:
In main thread
Output4:
In main thread
First thread execution
First thread execution
Output 1 to 3 are expected as main thread is not waiting child thread to exit. Execution sequence of both the threads (main and child) is fully dependent on Kernel thread scheduling.
But output 4 is strange !!! First thread execution gets printed two times !!!
Now if I run program after un-commentting code 'pthread_join(th1, NULL)' or add 'pthread_exit(NULL)', I do not get strange output (i.e. First thread execution never printed twice) ever, even I run code 10000 times.
My questions to experts are:
Without pthread_join/pthread_exit what is happening behind the scene so that First thread execution have got printed 2 times?
Responsibility of pthread_join is to get exit code of a particular thread, and after successful call of pthread_join, kernel will free resources of that particular thread. If I do not call pthread_join on a joinable thread then it will result in resource leak, but why above mentioned strange behavior ??
We might say, this is un-defined behavior, but it would be great if any expert provide technical explanation on this.
How pthread_join/pthread_exit can prevent above mentioned strange behavior ? What hidden thing it is doing here due to that strange behavior doesn't appear ?
Thanks to experts in advance..
I've observed this kind of double printing in a similar situation. While your thread was waiting in the write system call doing its normal output, specifically, in this stack:
#0 0x00007ffff78f4640 in write () from /lib64/libc.so.6
#1 0x00007ffff788fb93 in _IO_file_write () from /lib64/libc.so.6
#2 0x00007ffff788fa72 in new_do_write () from /lib64/libc.so.6
#3 0x00007ffff7890e05 in _IO_do_write () from /lib64/libc.so.6
#4 0x00007ffff789114f in _IO_file_overflow () from /lib64/libc.so.6
the program was terminated normally, normal termination caused the output subsystem to flush all buffers. The output buffer on stdin was not yet marked free (the write system call didn't return yet), so it was written out again:
#0 0x00007ffff78f4640 in write () from /lib64/libc.so.6
#1 0x00007ffff788fb93 in _IO_file_write () from /lib64/libc.so.6
#2 0x00007ffff788fa72 in new_do_write () from /lib64/libc.so.6
#3 0x00007ffff7890e05 in _IO_do_write () from /lib64/libc.so.6
#4 0x00007ffff7890140 in _IO_file_sync () from /lib64/libc.so.6
#5 0x00007ffff7891f56 in _IO_default_setbuf () from /lib64/libc.so.6
#6 0x00007ffff7890179 in _IO_file_setbuf () from /lib64/libc.so.6
#7 0x00007ffff7892703 in _IO_cleanup () from /lib64/libc.so.6
#8 0x00007ffff78512f8 in __run_exit_handlers () from /lib64/libc.so.
In any case, join your threads (If you used C++ threads, it would have reminded you to do that) or otherwise synchronize access to the output stream.
The main thread might end earlier then the spawned thread.
Ending the main thread implies ending the whole process, along with all threads being brought down abruptly. This might invoke undefined behaviour, thus anything can happen.
To get around this
either join the spawned thread using pthread_join() from main(),
or end the main thread using pthread_exit(), which just ends the main thread and keeps the process from being ended.
I'm communicating with a hardware device using QSerialPort. New data does not emit the "readyRead"-Signal, so I decided to write a read thread using QThread.
This is the code:
void ReadThread::run()
{
while(true){
readData();
if (buffer.size() > 0) parseData();
}
}
and
void ReadThread::readData()
{
buffer.append(device->readAll();
}
with buffer being an private QByteArray and device being a pointer to the QSerialPort. ParseData will parse the data and emit some signals. Buffer is cleared when parseData is left.
This works, however after some time (sometimes 10 seconds, sometimes 1 hour) the program crashes with SIGSEGV with the following trace:
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff3498700 (LWP 24870)]
malloc_consolidate (av=av#entry=0x7fffec000020) at malloc.c:4151
(gdb) bt
#0 malloc_consolidate (av=av#entry=0x7fffec000020) at malloc.c:4151
#1 0x00007ffff62c2ee8 in _int_malloc (av=av#entry=0x7fffec000020, bytes=bytes#entry=32769) at malloc.c:3423
#2 0x00007ffff62c4661 in _int_realloc (av=av#entry=0x7fffec000020, oldp=oldp#entry=0x7fffec0013b0, oldsize=oldsize#entry=64, nb=nb#entry=32784) at malloc.c:4286
#3 0x00007ffff62c57b9 in __GI___libc_realloc (oldmem=0x7fffec0013c0, bytes=32768) at malloc.c:3029
#4 0x00007ffff70d1cdd in QByteArray::reallocData(unsigned int, QFlags<QArrayData::AllocationOption>) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#5 0x00007ffff70d1f07 in QByteArray::resize(int) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#6 0x00007ffff799f9fc in free (bytes=<optimized out>, this=0x609458)
at ../../include/QtSerialPort/5.3.2/QtSerialPort/private/../../../../../src/serialport/qt4support/include/private/qringbuffer_p.h:140
#7 read (maxLength=<optimized out>, data=<optimized out>, this=0x609458)
at ../../include/QtSerialPort/5.3.2/QtSerialPort/private/../../../../../src/serialport/qt4support/include/private/qringbuffer_p.h:326
#8 QSerialPort::readData (this=<optimized out>, data=<optimized out>, maxSize=<optimized out>) at qserialport.cpp:1341
#9 0x00007ffff722bdf0 in QIODevice::read(char*, long long) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#10 0x00007ffff722cbaf in QIODevice::readAll() () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#11 0x00007ffff7bd0741 in readThread::readData (this=0x6066c0) at ../reader.cpp:212
#12 0x00007ffff7bc80d0 in readThread::run (this=0x6066c0) at ../reader.cpp:16
#13 0x00007ffff70cdd2e in ?? () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#14 0x00007ffff6e1c0a4 in start_thread (arg=0x7ffff3498700) at pthread_create.c:309
#15 0x00007ffff632f04d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111
I'm not sure how to reproduce the problem correctly, since it appears randomly. If I comment out the "readData()" in my while loop, the crashes do not appear anymore (of course no data can be parsed, then).
Does anyone have a clue what this could be?
What is the buffer? Could it be, another thread is reading the data from the buffer and clears it afterwards?
Try to lock it (and all other data shared between threads) e.g. with a mutex
QMutex mx; // could be also member of the ReadThread class
void ReadThread::readData()
{
mx.lock();
buffer.append(device->readAll();
mx.unlock();
}
And do the same in the code which reads and clears the buffer from another thread (I'm not doing the assumption, that this is parseData())
Another possibility could be, parseData() calls some code running in GUI-Thread. This doesn't work in Qt4 and probably also in Qt5
You're using the instance of a QObject from multiple threads at once. This generally speaking leads to undefined behavior, as you've just seen. QSerialPort will work just fine on the GUI thread. Only once you get it to work there, you can move it to a worker thread.
Note that if the event loop (app.exec() call in main() or QThread::run()) isn't executing, the signals won't be happening. It looks as if you tried to write pseudo synchronous code and have (predictably) failed. Don't do that.
Something like this is supposed to work:
#include <QtCore>
#include <QtSerialPort>
int main(int argc, char ** argv) {
QCoreApplication app(argc, argv);
QSerialPort port;
port.setPortName(...);
port.setBaudRate(...);
... // etc
if (! port.open(QIODevice::ReadWrite)) {
qWarning() << "can't open the port";
return 1;
}
... // set the port
connect(&port, &QIODevice::readyRead, [&]{
qDebug() << "got" << port.readAll().size() << "bytes";
});
return app.exec(); // the signals will be emitted from here
}
Ensure that all serial port related objects are initialized and used only in the separate thread. Send received data or parsed events to the UI thread by using signal/slot-mechanism.
Note also that if you inherit QThread in readThread, the constructor may be executed in the UI thread and other functions in the readThread. In that case, start the readThread and run separate initialization function before other functions (for example, by sending proper signal from the UI thread).
Can you tell me how can I use threads in C++ programs, and how can I compile it as it will be multithreaded? Can you tell me some good site where I can start from root?
Thanks
I haven't used it myself, but I'm told that the Boost thread libraries make it incredibly easy.
http://www.boost.org/doc/libs/1_37_0/doc/html/thread.html
For Unix/Linux/BSD, there's pthread library: tutorial.
I guess there are equivalent in Win32 API.
Process and Threads
Synchronization
I use tbb_thread class from intel threading building blocks library.
There are many threads libraries wich are compatible with c++. So at first you must select one. I prefer OpenMP or POSIX threads (also known as pthreads). How to compile it depends on library you have choose.
I use a library my university prof wrote. It is very simple to implement and works really well (used it for quite some time now). I will ask his permission to share it with you.
Sorry for the wait ahead, but gotta check :)
++++++EDIT+++++++
Ok, so I talked to my prof and he doesn't mind if I share it here. Below are the .h and .cpp files for the 'RT Library' written by Paul Davies
http://www.filefactory.com/file/7efbeb/n/rt_h
http://www.filefactory.com/file/40d9a6/n/rt_cpp
Some points to be made about threads and the use of this library:
0) This tutorial will explain thread creation and use on a windows platform.
1) Threads in c++ are usually coded as part of the same source (unlike processes where each process has its own source file and function main() )
2) When a process is up and running, it can create other threads by making appropriate Kernel calls.
3) Multiple threads run faster than multiple processes since they are a part of the same process which results in less of an overhead for the OS, and reduced memory requirements.
4) What you will be using in your case is the CThread class in the rt library.
5) (Make sure rt.h and rt.cpp are a part of your 'solution' and make sure to include rt.h in your main.cpp)
6) Below is a part of code from your future main thread (in main.cpp, of course) where you will create the thread using the CThread class.
void main()
{
CThread t1(ChildThread1, ACTIVE, NULL) ;
. . .
t1.WaitForThread() ; // if thread already dead, then proceed, otherwise wait
}
The arguments of t1 in order are: Name of the function acting as our thread, the thread status (it can be either ACTIVE or SUSPENDED - depending on what you want), and last, a pointer to an optional data you may want to pass to the thread at creation. After you execute some code, you'll want to call the WaitForThread() function.
7) Below is a part of code from your future main thread (in main.cpp, of course) where you will describe what the child thread does.
UINT _ _stdcall ChildThread1(void *args)
{
. . .
}
The odd looking thing there is Microsoft's thread signature. I'm sure with a bit of research you can figure out how to do this in other OSs. The argument is the optional data that could be passed to the child at creation.
8) You can find the detailed descriptions of the member functions in the rt.cpp file. Here are the summaries:
CThread() - The constructor responsible for creating the thread
Suspend() - Suspends a child thread effectively pausing it.
Resume() - Wakes up a suspended child thread
SetPriority(int value) - Changes the priority of a child thread to the value
specified
Post(int message) - Posts a message to a child thread
TerminateThread() - Terminates or Kills a child thread
WaitForThread() - Pauses the parent thread until a child thread terminates.
If the child thread has already terminated, parent will not pause
9) Below is an example of a sample complete program. A clever thing you can do is create multiple instantiations of a single thread.
#include “..\wherever\it\is\rt.h” //notice the windows notation
int ThreadNum[8] = {0,1,2,3,4,5,6,7} ; // an array of thread numbers
UINT _ _stdcall ChildThread (void *args) // A thread function
{
MyThreadNumber = *(int *)(args);
for ( int i = 0; i < 100; i ++)
printf( "I am the Child thread: My thread number is [%d] \n", MyThreadNumber) ;
return 0 ;
}
int main()
{
CThread *Threads[8] ;
// Create 8 instances of the above thread code and let each thread know which number it is.
for ( int i = 0; i < 8; i ++) {
printf ("Parent Thread: Creating Child Thread %d in Active State\n", i) ;
Threads[i] = new CThread (ChildThread, ACTIVE, &ThreadNum[i]) ;
}
// wait for threads to terminate, then delete thread objects we created above
for( i = 0; i < 8; i ++) {
Threads[i]->WaitForThread() ;
delete Threads[i] ; // delete the object created by ‘new’
}
return 0 ;
}
10) That's it! The rt library includes a bunch of classes that enables you to work with processes and threads and other concurrent programming techniques. Discover the rest ;)
You may want to read my earlier posting on SO.
(In hindsight, that posting is a little one-sided towards pthreads. But I'm a Unix/Linux kind of guy. And that approach seemed best with respect to the original topic.)
Usage of threads in C/C++:
#include <iostream>
using namespace std;
extern "C"
{
#include <stdlib.h>
#include <pthread.h>
void *print_message_function( void *ptr );
}
int main()
{
pthread_t thread1, thread2;
char *message1 = "Thread 1";
char *message2 = "Thread 2";
int iret1, iret2;
iret1 = pthread_create( &thread1, NULL, print_message_function (void*) message1);
iret2 = pthread_create( &thread2, NULL, print_message_function, (void*) message2);
pthread_join( thread1, NULL);
pthread_join( thread2, NULL);
//printf("Thread 1 returns: %d\n",iret1);
//printf("Thread 2 returns: %d\n",iret2);
cout<<"Thread 1 returns: %d\n"<<iret1;
cout<<"Thread 2 returns: %d\n"<<iret2;
exit(0);
}
void *print_message_function( void *ptr )
{
char *message;
message = (char *) ptr;
//printf("%s \n", message);
cout<<"%s"<<message;
}