问题
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;
}
回答1:
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.
来源:https://stackoverflow.com/questions/42395844/glib-gmaincontext-in-a-thread