cups-browsed uses GMainLoop and global variables, how to introduce locks against race conditions?
Till Kamppeter
till.kamppeter at gmail.com
Fri Dec 2 18:13:22 UTC 2016
On 12/02/2016 02:28 PM, Ted Gould wrote:
> On Fri, 2016-12-02 at 12:58 -0200, Till Kamppeter wrote:
>> The solution would be to acquire a lock when starting to manipulate the
>> printer list and releasing the lock when done.
>>
>> Now my qestion is, which functions I have to use for acquiring and
>> releasing locks when using GLib and GMainLoop? Probably it is not
>> correct to use the locks of pthread. Also it is probably best to use
>> Read/Write locks where only writing is exclusive but reading is allowed
>> to more than one thread at a time.
>
> Generally speaking the best way to do this is to use the mainloop itself
> as the lock. The mainloop is always on a single thread, so you should
> have the other threads put events into the main loop context and have
> them operate there on the data structure. So you'd, for instance, get
> all the information together on your Bonjour thread and when you're
> ready to add it put an action on the main loop with all that information.
>
> The functions you're probably looking for are (as starting points):
>
> g_main_context_get_thread_default()
> g_idle_source_new()
> g_source_attach()
>
The way how cups-browsed works is the following:
First, a GMainLoop is created:
gmainloop = g_main_loop_new (NULL, FALSE);
Browsing for legacy CUPS broadcasts is attached to the mail loop via
GIOChannel *browse_channel = g_io_channel_unix_new (browsesocket);
g_io_channel_set_close_on_unref (browse_channel, FALSE);
g_io_add_watch (browse_channel, G_IO_IN, process_browse_data, NULL);
Many other things are added via
g_idle_add ()
and
g_timeout_add_seconds ()
Reaction to D-Bus notifications is added via the
g_signal_connect()
function.
Avahi browsing is set up with these calls
/* Allocate main loop object */
if (!glib_poll)
if (!(glib_poll = avahi_glib_poll_new(NULL, G_PRIORITY_DEFAULT)))
{
debug_printf("ERROR: Failed to create glib poll object.\n");
goto avahi_init_fail;
}
/* Allocate a new client */
if (!client)
client = avahi_client_new(avahi_glib_poll_get(glib_poll),
AVAHI_CLIENT_NO_FAIL,
client_callback, NULL, &error);
/* Check wether creating the client object succeeded */
if (!client) {
debug_printf("ERROR: Failed to create client: %s\n",
avahi_strerror(error));
goto avahi_init_fail;
}
Strange is that this Avahi browsing setup is done before creation of the
main loop. Also some g_timeout_add_seconds () calls are done before
creating the main loop.
After that, the main loop gets started via
g_main_loop_run (gmainloop);
My questions are now:
- Is this way everything attached to the main loop?
- Do I have to do function calls in the beginning and in the end of each
callback function to acquire and release a lock? Which ones?
- If something of this is not attached to the main loop, how do I attach it?
I do not explicitly start any new threads.
Till
More information about the ubuntu-devel
mailing list