Possible to run multiple main loops? - c

I'm working with both libfuse and the glib event interface and I've run into an issue where I need to run multiple main loops concurrently (glib's g_main_loop_run and fuse_loop_mt).
I've already attempted to created a detached thread for glib's event loop under a secondary context, e.g.:
static void *
event_loop(void *arg)
{
GMainLoop *event_loop;
GMainContext *context;
context = g_main_context_new();
g_main_context_push_thread_default(context);
event_loop = g_main_loop_new(context, FALSE);
g_main_loop_run(event_loop);
return NULL;
}
...
pthread_t event_thread;
pthread_attr_t thread_attr;
pthread_attr_init(&thread_attr);
pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
event_thread = pthread_create(&event_thread, &thread_attr,
event_loop, NULL);
However the glib event loop doesn't pick up on any of the fired events. Am I totally off-base here? What's the proper way to tackle multiple main loops?

The GLib main loop supports custom event sources. I don't know much about FUSE, but you might be able to run FUSE's main loop within another thread, and integrate its events into the GLib loop.
A quick search suggests that you might be able to use a lower-level FUSE API to write your own main loop, which could presumably be integrated more readily into GLib's by simply skipping the "loop" part.
In general, though, multiple main loops are just bad news; that's why they're called main loops. :) The best way to handle them is to eliminate them by hooking events directly into whatever loop works best for you. Unfortunately, not all APIs provide the sufficient hooks to make that possible.

Apart from setting up main loops in a separate thread or a process (from the little bit of experience I have had, separate process has worked better for me but then again thread might work well in your case), you can consider integrating fuse main loop in GLib's main loop (Unfortunately I have no prior experience with this). You can check this thread discussion about the same (in case you have not seen it already). As suggested at the end of the thread " Register the fuse device file descriptor
(fuse_chan_fd()) with the glib event loop. Then call fuse_chan_recv()
and fuse_session_process() when the event trigger". To track the fd you will need to use GIO(More info on Nokia developer page).
Hopefully this can provide some hints!

Related

What is the difference between gtk_idle_add() and gtk_main_context_invoke() in gtk2?

I have an application that spawns a worker thread by calling g_thread_new(). The worker thread has to send progress information or probably occuring errors to the main thread that is updating the GUI based on received data.
Currently I'm using:
gtk_main_context_invoke(NULL, (GSourceFunc)update_gui, data);
with first parameter (of type GMainContext*) equal to NULL to run update_gui() in main loop context so that the worker can proceed doing the actual work.
When browsing the documentation I found a function:
guint g_idle_add (GSourceFunc function, gpointer data);
Would this function be more suitable for my application or should I use a completely different function for event transmission from worker to main thread?
Those functions are equivalent. g_main_context_invoke() is a wrapper around g_idle_add() which avoids the need for message passing if called on a GMainContext which is owned by the current thread (which is not the case in your example, but is harmless).
Note that the function is g_main_context_invoke(), not gtk_main_context_invoke(). To the best of my knowledge, the latter does not exist. Similarly, it’s g_idle_add() not gtk_idle_add().
Both g_main_context_invoke() and g_idle_add() are provided by GLib, not GTK. GTK uses GLib, but is not needed for this particular functionality.

Emit signal from separate thread in glib/gtk

I've programmed a GTK3 application in C. To speed up performance I want to put some calculations in separate threads. Currently I have not yet decided how to exactly implement it. But I think I will go with a GTask that I will trigger to run in a separate thread.
I want to to emit certain status updates about the calculation progress on my GUI.
They way I imagine this:
I've got a calculation GObject with a do_the_stuff_async() function that triggers the thread/GTask. Ideally, I want to connect to a 'progress-changed' signal which gives me the current status that I can display on my GUI. Also it would be great to trigger an event once the task has finished, which seems doable with a GTask
How do I safely emit a signal from a GTask/GThread to my GTK main loop?
Because I have not yet started implementing the asynchronous stuff: Is a GTask a suitable way for this or should I use something entirely different?
A GTask is suitable for this.
To emit the signal in a different thread:
Store the GMainContext of the main thread somewhere, and pass it into the GTask as task data.
When you want to emit a signal, create a GSource with g_idle_source_new(), add a callback for it, and attach it to the GMainContext of the main thread. That will make the callback be called in the main thread the next time the main thread’s context iterates.
The callback should call g_signal_emit() as appropriate.
Unless you want to make the GObject that you’re emitting the signal from thread safe, you should not pass it to the GTask worker thread. My general advice would be to avoid locking by only passing immutable objects to and from the worker thread.
Note that you could use g_idle_add() to create an idle GSource and add it to the global default GMainContext (the one GTK uses in the main thread). However, this makes the use of the GMainContext less explicit, and hence makes the code less maintainable. It’s not an approach which I would recommend in general.

NetworkManager libnm thread safety

I'm trying to use NetworkManager's libnm binding from a multithreaded program. Is libnm thread safe? I could not found any information about it.
libnm is written using glib and gobject. Although they don't seem to explicitly mention it in their doc, in general anything that uses glib runs on the main event loop and expects that the API will only be called on the main event loop (ie: on the thread that the event loop runs on).
Glib itself, however, is thread safe in general, or provides ways to ensure thread safety. For example, to connect to signal of libnm, you can use g_signal_connect from any thread; however the signal handler which you provide will be invoked on the thread running the main loop. Also, you can use something like g_idle_add from any thread, in order to schedule a function to be called from the main event loop.
You can also use the GTask lib to help you with threading in glib. Thre is more info about the Glib main context here.

Threading problems with GTK

I'm building a fairly simple C application using GTK, but have to perform some blocking IO which will trigger updates to the GUI. In order to do this, I start a new pthread right before gtk_main() as such:
/* global variables */
GMainContext *mainc;
/* local variables */
FILE *fifo;
pthread_t reader;
/* main() */
mainc = g_main_context_default();
pthread_create(&reader, NULL, watch_fifo, argv[argc-1]);
gtk_main();
When the pthread reads some data, it updates the GUI like so:
g_main_context_invoke(mainc, set_icon, param);
Where set_icon is
gboolean set_icon(gpointer data)
{
char *p = (char*)data;
gtk_status_icon_set_from_icon_name(icon, p);
return FALSE;
}
This all works most of the time, but every now and again I get this curious error message:
[xcb] Unknown sequence number while processing queue
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
mktrayicon: xcb_io.c:274: poll_for_event: Assertion `!xcb_xlib_threads_sequence_lost' failed.
I thought the whole point of using g_main_context_invoke was to avoid issues with threads? Doing a bit of Googling, I came across gdk_threads_init, gdk_threads_enter and friends, but they all seem to be deprecated? I know the GTK documentation says that all GUI updaes should be performed on the main thread, but this does not combine all that well with blocking IO, and I'd prefer not to have to construct some complex communication mechanism between the threads.
And so, my question is, how should I correctly deal with this?
EDIT: The full code can be seen here
EDIT2: As an update based on #ptomato's answer, I've moved to GThreads and using gdk_threads_add_idle() as seen in this commit, but the problem is still present.
Call XInitThreads(). This should be done before gtk_init, that will stop the messages!
Something like this:
#include <X11/Xlib.h>
...
XInitThreads();
...
gtk_init(&argc, &argv);
I don't remember seeing these messages before GLIB 2.32, when
g_thread_init()/gdk_threads_init() were used.
You might want to check out g_thread_pool_new and g_thread_pool_push.
From thread, use g_main_context_invoke to execute in main loop or
just wrap thread between gdk_threads_enter()/gdk_threads_leave()
I do not use a tray so I can not easily check this. I think you are
correct about gdk_threads_add_idle using locks to protect GTK/GDK API.
There is nothing obvious to me that would cause these messages to
appear. The function description for gtk_status_icon_new_from_icon_name
states that "If the current icon theme is changed, the icon will be
updated appropriately. Which to me, implies your code is not the only
code that will access the X display, which could potentially be the
problem.
There is also some related info regarding XInitThreads() at
What is the downside of XInitThreads()?
Note that while GDK uses locks for the display, GTK/GDK do not ever
call XInitThreads.
On a side note: What's protecting the global variable "onclick", which
is passed to execl after a fork(), The child will not inherit the parent's
memory locks, and GLib mainloop is incompatible with fork().
Maybe you could copy the string to local variable.
I'm not sure if bare pthreads are guaranteed to work with GTK. You should use the GThread wrappers.
I think what the problem may be is that g_main_context_invoke() is adding set_icon() as an idle function. (It seems that that is what goes on behind the scenes, but I'm not sure.) Idle functions added using GLib's API, despite being executed on the main thread, need to hold the GDK lock. If you use the gdk_threads_add_idle() API (which is not deprecated) to invoke set_icon(), then everything should work properly with threading.
(Although this is just a wild guess.)
As a work around, if you just want to avoid blocking the UI while waiting for some IO you could use the asynchronous IO from GIO. That would avoid you having to manage threads yourself.
Edit: Thinking about it you could just mark your file descriptors as non-blocking and add them as a source to the glib main loop and it will poll them for you in the main event loop without having to mess about with threads.
You could avoid using threads by using gio_add_watch() which will invoke your callback function when there is data available on the channel.

Is using timers/signals in c static libraries bad practice?

I'm building two static c libraries. Each of the libraries have a routine that needs to run once every second after calling mylib_init();
I implemented this in each library using setitimer, which uses the ITIMER_REAL resource and the SIGALRM signal.
void Start1msTimer()
{
struct itimerval new;
memset(&new,0, sizeof(new));
new.it_interval.tv_sec=1;
new.it_value.tv_sec=1;
signal (SIGALRM, OneSecTimeout);
setitimer (ITIMER_REAL, &new,NULL);
}
Ok so far so good everything was working.
Now I'm building a sample application that uses both of these libraries, and conflicts are arising. I have realized an application can only have one handler for each signal, and ITIMER_REAL can only be used for one timer, not both. So obviously things are not working now.
What would be a better way for me to implement the timing in each of my libraries?
In general, is it a bad idea to have any signal handlers inside of a library?
Yes, it's a very bad idea to "use up" application-level resources in a library, since the application developer using the library won't get a say in how the resources should be allocated.
And, as you discovered, you get interoperability problems when multiple libraries want to own the same resource.
One way to fix this is to factor out the requirement, have a function mylib_update() and document that the application must call it once a second. That leaves the question of how to implement such a timer-based updating to the application, where it belongs.
You could use threads + a syncronization method. Instead of writing a signal handler, you write a thread. Using a semaphore, you can even run your event thread either on timeout or on demand (ie the app calls a library function that post the semaphore).

Resources