Proper program structure using g_main_loop - c

I have an application that requires use of callback functions that will not fire unless the glib g_main_loop is running. I am hazy on what a "good" program would look like implementing this, or what the expected program flow would be. I dont feel what I have seems correct because this method requires looping after every function that is asycn, to wait for the response. I would imagine there must be some way to spawn off the g_main_loop without it blocking, but Im not aware of how to achieve that.
Here is pseudo-code for what I have to achieve usage of the function requiring callback:
// declared globally so it can be started from main, stopped from callback.
GMainLoop *loop;
void callback_function(void)
{
g_main_loop_quit(loop);
}
int main (void)
{
func_which_requires_callback(callback_function);
loop = g_main_loop_new();
// loop will end when callback ends the loop
return 0;
}

Your pseudocode is pretty much right. All the work is done in callbacks, while the main loop iterates. The callbacks are either triggered by asynchronous operations, or event sources such as g_idle_add(), or they are signal handlers.

Related

Does make any sense using cleanup code after an infinite loop?

I'm reading code for a linux daemon and its main() function is structured like this:
int main(int argc, char **argv){
// code which spawns some worker threads, sets up some
// signal handlers for clean termination, etc.
// ...
for(;;){ sleep(1); }
p_clean_exit();
return 0;
}
As it stands this makes no sense to me.
The for loop will keep the process alive, waking every sencond, then going back to sleep.
p_clean_exit() wil never be called nor 0 will be returned from the last statement.
Of course there's code elsewhere which sends signals, and and installed handlers which in turn call p-clen_exit() on their own for program termination. But this one instance here will never be reached. Right?
Does this make actual sense under some circumstance?
Does this make actual sense under some circumstance?
None of the code in your example really makes much sense: there's no point in writing a daemon that wakes up once per second only to sleep again without doing anything. But it's okay, because this is just a sample... it's the skeleton of a daemon, and it's understood that you'll add code inside that loop that does something interesting. The code that you add might call break or otherwise cause the loop to exit, and that's when it's good form to call p_clean_exit().
So yes, it's true that if you were to compile and run the code as is, the call to p_clean_exit() won't mean much. But no, it's not pointless to have it there, because the whole point of the code isn't to use it as is, it's to show you how to structure a real daemon, and a real daemon should absolutely clean up after itself.
Does this make actual sense under some circumstance?
Yes, there are function macros in C and there is Duff's case machine and setjmp function call in C. There may be a call to setjmp above that executes a switch and "jumps over" the endless loop to execute cleanup code, when a longjmp is executed from some code running concurrently to the main thread.
#define p_clean_init(context) switch (setjmp(context)) { case 0:
#define p_clean_exit() case 1: }
jmp_buf context;
int signal_handler(...) {
siglongjmp(context, 1);
}
int main() {
signal(..., signal_handler);
p_clean_init(context);
for(;;){ sleep(1); }
p_clean_exit();
}
There are pthread_cleanup_push and pthread_cleanup_pop functions that are used in a similar fashion - and from documentation we know that POSIX.1 permits pthread_cleanup_push() and pthread_cleanup_pop() to be implemented as macros that expand to text containing '{' and '}'. You may explore it's glibc implementation.
Maybe worth noting: by expanding macros to a switch(...) (but also to goto with labels as values GCC extension) is explored by pthreadthread project, the method used most notably by Contiki OS. But it would not work here unless the endless loop would yield periodically.

GLIB usage without mainloop

I have a problem using Glib. I want to subscribe to a dbus signal without launching the mainloop with g_main_loop_run.
I create the connection to the correct bus and call the function g_dbus_connection_signal_subscribe.
I replaced the call to g_main_loop_run in the main function by a while(1).
Unfortunately, it's not working. If I understand correctly the GLib, there is no need to launch the mainloop for a such treatment.
Please help.
Sample code :
session_bus = g_bus_get_sync(G_BUS_TYPE_SESSION,
NULL,
NULL );
g_dbus_connection_signal_subscribe(session_bus,
"org.freedesktop.Notifications",
"org.freedesktop.Notifications",
"NotificationClosed",
"/org/freedesktop/Notifications",
NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
(GDBusSignalCallback) onNotifClosed,
NULL,
NULL );
loop = g_main_loop_new(NULL, FALSE);
g_main_loop_run(loop);
g_main_loop_unref(loop);
g_object_unref(session_bus);
If I understand correctly the GLib, there is no need to launch the
mainloop for a such treatment.
If you want to wait for incoming DBus events, you have to run main loop. What main loop does is to wait and process events, and you want to wait and then process events. As an alternative to g_main_loop_run, you may try to run g_main_context_iteration in while(1).
I had a similar need to process GLib events in a non-blocking manner and I couldn't find a complete answer anywhere, so I'm posting my solution here for reference.
As el.pescado said, the one alternative to g_main_loop_run() is calling g_main_context_iteration() repeatedly on the context of the GMainLoop object. This may be done in a loop for example, allowing some intervening_task() to be performed between event processing cycles until some sort of termination_condition() is met:
GMainLoop *loop = g_main_loop_new();
while (!termination_condition())
{
g_main_context_iteration(g_main_loop_get_context(loop), FALSE);
intervening_task();
}
g_main_loop_unref(loop);
In the snippet above, the loop context is retrieved by g_main_loop_get_context(), and any pending GLib events are processed by g_main_context_iteration(). Setting the may_block argument to FALSE causes the function to return immediately if there are no pending events (otherwise it would block waiting for something to process).
It's worth noticing however that if the above is all you want to do, then you might as well stick to g_main_loop_run() and use g_timeout_add() or g_idle_add() to register the intervening task and termination condition as event callbacks — the later would call g_main_loop_quit() to terminate the loop. The point here is not to use that code as-is, but merely to demonstrate how GLib events can be processed in a non-blocking manner, so it can be integrated to the main loop of another framework. e.g. Qt or ROS.

calling same threadproc() multiple times, without first call finished

i have a threadProc
void* ThreadProc(void* xyz)
{
//do some work..
}
now from the main thread.. i call this thread and do not wish to wait for it to finish
WaitForSingleObject(hThread, 0)
now my flow of program is succh that the case may arrive where
first call to thread is not finished and 2nd time same ThreadProc() is called.
So ...
1. How does OS handles this scenario? Will this kind of program give unexpected results?
2. If this is wrong way of doing it, what is the correct way?
Because ultimately I want one function to be called asynchronously, may be running multiple instances at the same time.
Every thread has a separate stack, so as long as all variables in the thread callback function are local, there are no conflicts. But if you would access variables that are global/static, then they are shared between all threads and all access to them needs to be handled carefully. Use mutex/semaphores/critical sections for such. The same goes for calling library functions which you don't know are thread-safe.
Will this kind of program give unexpected results?
That depends entirely on the body of the thread callback function. You should however wait using WaitForSingleObject(hThread, INFINITE). Right now you wait 0ms, which does nothing.

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.

Threads in userspace and yield

I am supposed to implement a userlevel threads library in C. To do so, I need to implement yield(), createThread() and destroyThread() functions. I believe I've got the basics right:
To keep track of threads, I'll use a queue of ThreadControlBlock elements (which resemble PCBs in an OS) that look like this:
struct ThreadControlBlock {
int ThreadId,
u_context *context };
We can use the setcontext() family of functions to "save" and "load" the context.
Upon initialization of the program, initialize ThreadQueue with no elements.
Now the part I am not getting: when a thread calls yield(), I get the current context and save it in a ThreadControlBlock and put in the queue. Then get the first element in the queue and load the context in it, and execution proceeds.
The question is, if I do this, say I am a thread calling yield() and the next thread is myself. If I am saving the context and loading it again, upon re-entering wouldn't I be at the exact same spot where I was (before calling yield()?) And this would keep going on forever?
When a thread calls yield(), you have to save the state of a thread that's about to return from a yield() call. Don't save the context from immediately before the yield().
The same issue actually applies if you're switching to another task, too - since that other task saved its context at the same point (where it was about to switch to a second task). Using setcontext() and getcontext(), you need to use a static variable to keep track of whether you're switching in or switching out:
static volatile int switched;
switched = 0;
getcontext(current->context);
if (!switched)
{
switched = 1;
setcontext(next->context);
}
Alternatively, you can just use swapcontext(current->context, next->context);
It's perfectly reasonable in your yield() implementation to check to see if the next thread is the current thread and treat that case as a no-op.
If there are no other threads to run besides the current thread then there is nothing else to do besides just return from yield. I wouldn't bother with calling swapcontext in this case, though -- just detect and return.
I think that what you are actually dealing with is what to do when no threads (including the current one) when yield is called. An easy way to deal with this is to have an idle thread, which is only run when the run queue (ready threads) is empty. This thread will probably just:
{
while (1) {
yield();
pause();
}
}
This allows your program to go to sleep (via pause) until a signal happens. Hopefully the signal will be some event that makes one of the other threads ready to run, so the next call to yield will run the other thread instead of running the idle thread again.

Resources