I have searched on stack overflow to find answer relevant to my problem. But i didn't find any answer.
I have a main thread (my main() function) which starts a thread. The new thread runs GMainLoop. In my main function, i keep adding sources by calling g_io_watch over some file descriptors. But i have getting garbage data if events are dispatched.
Below is a small part of the code that i am trying:
GMainLoop *loop;
gpointer event_loop_thread(gpointer arg)
{
g_main_loop_run(loop);
g_main_loop_unref(loop);
return NULL;
}
int init()
{
loop = g_main_loop_new(NULL, FALSE);
g_thread_new(NULL, event_loop_thread, NULL);
return 0;
}
gboolean __hci_service(GIOChannel *source, GIOCondition condition, gpointer data)
{
// Doing something
return FALSE;
}
int main()
{
init();
int _adapter_id = hci_devid("hci0");
int hci_dev = hci_open_dev(_adapter_id);
GIOChannel *p_hci_io = g_io_channel_unix_new(dev_id);
GIOCondition cond = (GIOCondition)(G_IO_IN);
g_io_add_watch(p_hci_io, cond, __hci_service, NULL);
while (true);
// I will close file descriptor
return 0;
}
However, if i try this code, then everything works as expected:
GMainLoop *loop;
gpointer event_loop_thread(gpointer arg)
{
g_main_loop_run(loop);
g_main_loop_unref(loop);
return NULL;
}
int init()
{
loop = g_main_loop_new(NULL, FALSE);
g_thread_new(NULL, event_loop_thread, NULL);
return 0;
}
gboolean __hci_service(GIOChannel *source, GIOCondition condition, gpointer data)
{
// Doing something
return FALSE;
}
int main()
{
// init();
int _adapter_id = hci_devid("hci0");
int hci_dev = hci_open_dev(_adapter_id);
GIOChannel *p_hci_io = g_io_channel_unix_new(dev_id);
GIOCondition cond = (GIOCondition)(G_IO_IN);
g_io_add_watch(p_hci_io, cond, __hci_service, NULL);
loop = g_main_loop_new(NULL, FALSE);
g_main_loop_run(loop);
g_main_loop_unref(loop);
while (true);
// I will close file descriptor
return 0;
}
Edit:
I have tried passing the default GMainContext of the main thread to the newly created thread. Have a look. Tell me if my approach is correct.
GMainLoop *loop;
gpointer event_loop_thread(gpointer arg)
{
GMainContext *context = (GMainContext *)arg;
loop = g_main_loop_new(context, FALSE);
g_main_context_push_thread_default(context);
g_main_loop_run(loop);
g_main_loop_unref(loop);
return NULL;
}
int init()
{
g_thread_new(NULL, event_loop_thread, (gpointer)g_main_context_default());
return 0;
}
gboolean __hci_service(GIOChannel *source, GIOCondition condition, gpointer data)
{
// Doing something
return FALSE;
}
int main()
{
init();
int _adapter_id = hci_devid("hci0");
int hci_dev = hci_open_dev(_adapter_id);
GIOChannel *p_hci_io = g_io_channel_unix_new(dev_id);
GIOCondition cond = (GIOCondition)(G_IO_IN);
g_io_add_watch(p_hci_io, cond, __hci_service, NULL);
//loop = g_main_loop_new(NULL, FALSE);
//g_main_loop_run(loop);
//g_main_loop_unref(loop);
while (true);
// I will close file descriptor
return 0;
}
You need to use GMainContext if you want to run a main loop from a thread. From the Glib's main loop documentation:
To allow multiple independent sets of sources to be handled in different threads, each source is associated with a GMainContext. A GMainContext can only be running in a single thread, but sources can be added to it and removed from it from other threads.
When you create a main loop with g_main_loop_new(NULL, FALSE);, while it's handy to not specify any GMainContext, you need to pass a GMainContext from which you want your loop if you want to run the loop in a different thread. You can create a GMainContext with g_main_context_new() and pass it to g_main_loop_new(), or use g_main_context_get_thread_default() to get the default main context for the running thread.
g_io_add_watch() is yet another handy version of the function, which
Adds the GIOChannel into the default main loop context with the default priority.
Unfortunately, there is no g_io_add_watch() variant function to specify a main context, you have to manually create a GSource from your GIOChannel, p_hci_io, and attach to your context via g_source_attach(). Note that g_io_add_watch_full() also works with the default main context.
The reason your second code works is that you created your main loop in the main thread which has your source attached.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With