[glib-networking] proxy/gnome: fix up threading issues and other bugs
- From: Dan Winship <danw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib-networking] proxy/gnome: fix up threading issues and other bugs
- Date: Tue, 5 Feb 2013 15:15:17 +0000 (UTC)
commit 55f2bb4a47e4e450f1d065bcfe242cafcacc571e
Author: Dan Winship <danw gnome org>
Date: Mon Jan 28 10:45:31 2013 -0500
proxy/gnome: fix up threading issues and other bugs
We had a mutex to deal with the possibility of multi-threaded use, but
were unlocking it too soon, so there wasn't any actual thread safety
(or at least, not much) if GProxyResolverGnome was being used from
multiple threads at the moment that the GSettings were changed.
Additionally, lookup_async() wasn't noticing updates to the settings
if they switched from automatic to manual/direct, and if they switched
from in the other direction, then the first lookup_async() call after
the change would end up making a synchronous call to the pacrunner.
Also, fix two cases where an operation could return both a list of
proxies and a GError.
proxy/gnome/gproxyresolvergnome.c | 188 ++++++++++++++++++++++++------------
1 files changed, 125 insertions(+), 63 deletions(-)
---
diff --git a/proxy/gnome/gproxyresolvergnome.c b/proxy/gnome/gproxyresolvergnome.c
index ae046d4..44e104c 100644
--- a/proxy/gnome/gproxyresolvergnome.c
+++ b/proxy/gnome/gproxyresolvergnome.c
@@ -451,26 +451,49 @@ ignore_host (GProxyResolverGnome *resolver,
return ignore;
}
-static gchar **
-g_proxy_resolver_gnome_lookup (GProxyResolver *proxy_resolver,
- const gchar *uri,
- GCancellable *cancellable,
- GError **error)
+static inline gchar **
+make_proxies (const gchar *proxy)
+{
+ gchar **proxies;
+
+ proxies = g_new (gchar *, 2);
+ proxies[0] = g_strdup (proxy);
+ proxies[1] = NULL;
+
+ return proxies;
+}
+
+/* Threadsafely determines what to do with @uri; returns %FALSE if an
+ * error occurs, %TRUE and an array of proxies if the mode is NONE or
+ * MANUAL, or if @uri is covered by ignore-hosts, or %TRUE and a
+ * (transfer-full) pacrunner and autoconfig url if the mode is AUTOMATIC.
+ */
+static gboolean
+g_proxy_resolver_gnome_lookup_internal (GProxyResolverGnome *resolver,
+ const gchar *uri,
+ gchar ***out_proxies,
+ GDBusProxy **out_pacrunner,
+ gchar **out_autoconfig_url,
+ GCancellable *cancellable,
+ GError **error)
{
- GProxyResolverGnome *resolver = G_PROXY_RESOLVER_GNOME (proxy_resolver);
GSocketConnectable *addr = NULL;
const gchar *scheme = NULL, *host = NULL;
- const gchar *proxy = "direct://";
- gchar **proxies = NULL;
gushort port;
+ *out_proxies = NULL;
+ *out_pacrunner = NULL;
+ *out_autoconfig_url = NULL;
+
g_mutex_lock (&resolver->lock);
if (resolver->need_update)
update_settings (resolver);
- g_mutex_unlock (&resolver->lock);
if (resolver->mode == G_DESKTOP_PROXY_MODE_NONE)
- goto done;
+ {
+ *out_proxies = make_proxies ("direct://");
+ goto done;
+ }
/* FIXME: use guri when it lands... */
addr = g_network_address_parse_uri (uri, 0, error);
@@ -481,61 +504,96 @@ g_proxy_resolver_gnome_lookup (GProxyResolver *proxy_resolver,
port = g_network_address_get_port (G_NETWORK_ADDRESS (addr));
if (ignore_host (resolver, host, port))
- goto done;
+ {
+ *out_proxies = make_proxies ("direct://");
+ goto done;
+ }
if (resolver->pacrunner)
{
- GVariant *vproxies;
-
- vproxies = g_dbus_proxy_call_sync (resolver->pacrunner,
- "Lookup",
- g_variant_new ("(ss)",
- resolver->autoconfig_url,
- uri),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- cancellable, error);
- if (vproxies)
- {
- g_variant_get (vproxies, "(^as)", &proxies);
- g_variant_unref (vproxies);
- }
+ *out_pacrunner = g_object_ref (resolver->pacrunner);
+ *out_autoconfig_url = g_strdup (resolver->autoconfig_url);
+ goto done;
}
else if (resolver->ftp_proxy &&
(!strcmp (scheme, "ftp") || !strcmp (scheme, "ftps")))
{
- proxy = resolver->ftp_proxy;
+ *out_proxies = make_proxies (resolver->ftp_proxy);
}
else if (resolver->https_proxy && !strcmp (scheme, "https"))
{
- proxy = resolver->https_proxy;
+ *out_proxies = make_proxies (resolver->https_proxy);
}
else if (resolver->http_proxy &&
(!strcmp (scheme, "http") || !strcmp (scheme, "https")))
{
- proxy = resolver->http_proxy;
+ *out_proxies = make_proxies (resolver->http_proxy);
}
else if (resolver->socks_authority)
{
- proxies = g_new0 (gchar *, 4);
- proxies[0] = g_strdup_printf ("socks5://%s", resolver->socks_authority);
- proxies[1] = g_strdup_printf ("socks4a://%s", resolver->socks_authority);
- proxies[2] = g_strdup_printf ("socks4://%s", resolver->socks_authority);
+ *out_proxies = g_new (gchar *, 4);
+ *out_proxies[0] = g_strdup_printf ("socks5://%s", resolver->socks_authority);
+ *out_proxies[1] = g_strdup_printf ("socks4a://%s", resolver->socks_authority);
+ *out_proxies[2] = g_strdup_printf ("socks4://%s", resolver->socks_authority);
+ *out_proxies[3] = NULL;
}
else if (resolver->use_same_proxy && resolver->http_proxy)
{
- proxy = resolver->http_proxy;
+ *out_proxies = make_proxies (resolver->http_proxy);
}
+ else
+ *out_proxies = make_proxies ("direct://");
done:
if (addr)
g_object_unref (addr);
+ g_mutex_unlock (&resolver->lock);
- if (!proxies)
+ if (*out_proxies || *out_pacrunner)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static gchar **
+g_proxy_resolver_gnome_lookup (GProxyResolver *proxy_resolver,
+ const gchar *uri,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GProxyResolverGnome *resolver = G_PROXY_RESOLVER_GNOME (proxy_resolver);
+ GDBusProxy *pacrunner;
+ gchar **proxies, *autoconfig_url;
+
+ if (!g_proxy_resolver_gnome_lookup_internal (resolver, uri,
+ &proxies, &pacrunner, &autoconfig_url,
+ cancellable, error))
+ return NULL;
+
+ if (pacrunner)
{
- proxies = g_new0 (gchar *, 2);
- proxies[0] = g_strdup (proxy);
+ GVariant *vproxies;
+
+ vproxies = g_dbus_proxy_call_sync (pacrunner,
+ "Lookup",
+ g_variant_new ("(ss)",
+ autoconfig_url,
+ uri),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable, error);
+ if (vproxies)
+ {
+ g_variant_get (vproxies, "(^as)", &proxies);
+ g_variant_unref (vproxies);
+ }
+ else
+ proxies = NULL;
+
+ g_object_unref (pacrunner);
+ g_free (autoconfig_url);
}
+
return proxies;
}
@@ -571,35 +629,39 @@ g_proxy_resolver_gnome_lookup_async (GProxyResolver *proxy_resolver,
{
GProxyResolverGnome *resolver = G_PROXY_RESOLVER_GNOME (proxy_resolver);
GTask *task;
+ char **proxies, *autoconfig_url;
+ GDBusProxy *pacrunner;
+ GError *error = NULL;
task = g_task_new (resolver, cancellable, callback, user_data);
- if (resolver->pacrunner)
- {
- g_dbus_proxy_call (resolver->pacrunner,
- "Lookup",
- g_variant_new ("(ss)",
- resolver->autoconfig_url,
- uri),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- cancellable,
- got_autoconfig_proxies,
- task);
- }
- else
- {
- GError *error = NULL;
- char **proxies;
-
- proxies = g_proxy_resolver_gnome_lookup (proxy_resolver, uri,
- cancellable, &error);
- if (proxies)
- g_task_return_pointer (task, proxies, (GDestroyNotify)g_strfreev);
- else
- g_task_return_error (task, error);
- g_object_unref (task);
- }
+ if (!g_proxy_resolver_gnome_lookup_internal (resolver, uri,
+ &proxies, &pacrunner, &autoconfig_url,
+ cancellable, &error))
+ {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+ else if (proxies)
+ {
+ g_task_return_pointer (task, proxies, (GDestroyNotify)g_strfreev);
+ g_object_unref (task);
+ return;
+ }
+
+ g_dbus_proxy_call (pacrunner,
+ "Lookup",
+ g_variant_new ("(ss)",
+ autoconfig_url,
+ uri),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ got_autoconfig_proxies,
+ task);
+ g_object_unref (pacrunner);
+ g_free (autoconfig_url);
}
static gchar **
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]