public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
From: "Georgy Yakovlev" <gyakovlev@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Subject: [gentoo-commits] proj/musl:master commit in: dev-libs/glib/files/, dev-libs/glib/
Date: Wed, 26 Feb 2020 05:11:42 +0000 (UTC)	[thread overview]
Message-ID: <1582693825.a0694d1160bd9b7a7cd9c95744487e0d45d1e87b.gyakovlev@gentoo> (raw)

commit:     a0694d1160bd9b7a7cd9c95744487e0d45d1e87b
Author:     Georgy Yakovlev <gyakovlev <AT> gentoo <DOT> org>
AuthorDate: Wed Feb 26 05:10:25 2020 +0000
Commit:     Georgy Yakovlev <gyakovlev <AT> gentoo <DOT> org>
CommitDate: Wed Feb 26 05:10:25 2020 +0000
URL:        https://gitweb.gentoo.org/proj/musl.git/commit/?id=a0694d11

dev-libs/glib: bump to 2.60.7-r2 from ::gentoo

stable bug is still open for arm and arm64 #710514,
stabilize here right away, ince 2.60.7 already stable
on those arches

Package-Manager: Portage-2.3.89, Repoman-2.3.20
Signed-off-by: Georgy Yakovlev <gyakovlev <AT> gentoo.org>

 dev-libs/glib/Manifest                       |   1 +
 dev-libs/glib/files/2.60.7-gdbus-fixes.patch | 301 +++++++++++
 dev-libs/glib/files/CVE-2020-6750.patch      | 763 +++++++++++++++++++++++++++
 dev-libs/glib/glib-2.60.7-r2.ebuild          | 283 ++++++++++
 4 files changed, 1348 insertions(+)

diff --git a/dev-libs/glib/Manifest b/dev-libs/glib/Manifest
index ec53fc2..b26aefc 100644
--- a/dev-libs/glib/Manifest
+++ b/dev-libs/glib/Manifest
@@ -1 +1,2 @@
 DIST glib-2.60.6.tar.xz 4589516 BLAKE2B 33546aea288dee4aa8c04bda610a65ce75705c0e2b98284e787d42576c61eccbd33788084b092e030fe26c50ff08e398782227d1f2ac39ef9754b91af1ab1aa1 SHA512 2e079d2268e0cd4dd234501c03e7784a69258ea2303e62baa4869ff7a442d121c2ffdc742467e3b0b46ad953b831962e1dd847463d66b2b28745ba0f0bfd28d9
+DIST glib-2.60.7.tar.xz 4590568 BLAKE2B a3f2a3bd0443a27326e8359c2ad1e6022ca1634f5c7cb4502a8011fbe85df690fff7d67665cf160bf4ed426214b87f6501a69158fb1656bdb86cacdcf076ee15 SHA512 d56d805a5abf6f7aeb8bf5be06b60ad049177ee23f78eacef4ce2ea88a8be49966a95e48fed17c752649f6e80937fd0ebc8f959709f623ec1f2f43ffd42d078a

diff --git a/dev-libs/glib/files/2.60.7-gdbus-fixes.patch b/dev-libs/glib/files/2.60.7-gdbus-fixes.patch
new file mode 100644
index 0000000..e2a066b
--- /dev/null
+++ b/dev-libs/glib/files/2.60.7-gdbus-fixes.patch
@@ -0,0 +1,301 @@
+From 1cfab12a28d97716ad581c30fbbf3e94e4d7f303 Mon Sep 17 00:00:00 2001
+From: Simon McVittie <smcv@collabora.com>
+Date: Mon, 14 Oct 2019 08:22:24 +0100
+Subject: [PATCH 1/3] gcredentialsprivate: Document the various private macros
+
+Signed-off-by: Simon McVittie <smcv@collabora.com>
+---
+ gio/gcredentialsprivate.h | 59 +++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 59 insertions(+)
+
+diff --git a/gio/gcredentialsprivate.h b/gio/gcredentialsprivate.h
+index 4d1c420a8..06f0aed19 100644
+--- a/gio/gcredentialsprivate.h
++++ b/gio/gcredentialsprivate.h
+@@ -22,6 +22,65 @@
+ #include "gio/gcredentials.h"
+ #include "gio/gnetworking.h"
+ 
++/*
++ * G_CREDENTIALS_SUPPORTED:
++ *
++ * Defined to 1 if GCredentials works.
++ */
++#undef G_CREDENTIALS_SUPPORTED
++
++/*
++ * G_CREDENTIALS_USE_LINUX_UCRED, etc.:
++ *
++ * Defined to 1 if GCredentials uses Linux `struct ucred`, etc.
++ */
++#undef G_CREDENTIALS_USE_LINUX_UCRED
++#undef G_CREDENTIALS_USE_FREEBSD_CMSGCRED
++#undef G_CREDENTIALS_USE_NETBSD_UNPCBID
++#undef G_CREDENTIALS_USE_OPENBSD_SOCKPEERCRED
++#undef G_CREDENTIALS_USE_SOLARIS_UCRED
++
++/*
++ * G_CREDENTIALS_NATIVE_TYPE:
++ *
++ * Defined to one of G_CREDENTIALS_TYPE_LINUX_UCRED, etc.
++ */
++#undef G_CREDENTIALS_NATIVE_TYPE
++
++/*
++ * G_CREDENTIALS_NATIVE_SIZE:
++ *
++ * Defined to the size of the %G_CREDENTIALS_NATIVE_TYPE
++ */
++#undef G_CREDENTIALS_NATIVE_SIZE
++
++/*
++ * G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED:
++ *
++ * Defined to 1 if we have a message-passing API in which credentials
++ * are attached to a particular message, such as `SCM_CREDENTIALS` on Linux
++ * or `SCM_CREDS` on FreeBSD.
++ */
++#undef G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED
++
++/*
++ * G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED:
++ *
++ * Defined to 1 if we have a `getsockopt()`-style API in which one end of
++ * a socket connection can directly query the credentials of the process
++ * that initiated the other end, such as `getsockopt SO_PEERCRED` on Linux
++ * or `getpeereid()` on multiple operating systems.
++ */
++#undef G_CREDENTIALS_SOCKET_GET_CREDENTIALS_SUPPORTED
++
++/*
++ * G_CREDENTIALS_SPOOFING_SUPPORTED:
++ *
++ * Defined to 1 if privileged processes can spoof their credentials when
++ * using the message-passing API.
++ */
++#undef G_CREDENTIALS_SPOOFING_SUPPORTED
++
+ #ifdef __linux__
+ #define G_CREDENTIALS_SUPPORTED 1
+ #define G_CREDENTIALS_USE_LINUX_UCRED 1
+-- 
+2.20.1
+
+
+From 5f9318af8f19756685c1b79cf8b76f3e66614d84 Mon Sep 17 00:00:00 2001
+From: Simon McVittie <smcv@collabora.com>
+Date: Fri, 18 Oct 2019 10:55:09 +0100
+Subject: [PATCH 2/3] credentials: Invalid Linux struct ucred means "no
+ information"
+
+On Linux, if getsockopt SO_PEERCRED is used on a TCP socket, one
+might expect it to fail with an appropriate error like ENOTSUP or
+EPROTONOSUPPORT. However, it appears that in fact it succeeds, but
+yields a credentials structure with pid 0, uid -1 and gid -1. These
+are not real process, user and group IDs that can be allocated to a
+real process (pid 0 needs to be reserved to give kill(0) its documented
+special semantics, and similarly uid and gid -1 need to be reserved for
+setresuid() and setresgid()) so it is not meaningful to signal them to
+high-level API users.
+
+An API user with Linux-specific knowledge can still inspect these fields
+via g_credentials_get_native() if desired.
+
+Similarly, if SO_PASSCRED is used to receive a SCM_CREDENTIALS message
+on a receiving Unix socket, but the sending socket had not enabled
+SO_PASSCRED at the time that the message was sent, it is possible
+for it to succeed but yield a credentials structure with pid 0, uid
+/proc/sys/kernel/overflowuid and gid /proc/sys/kernel/overflowgid. Even
+if we were to read those pseudo-files, we cannot distinguish between
+the overflow IDs and a real process that legitimately has the same IDs
+(typically they are set to 'nobody' and 'nogroup', which can be used
+by a real process), so we detect this situation by noticing that
+pid == 0, and to save syscalls we do not read the overflow IDs from
+/proc at all.
+
+This results in a small API change: g_credentials_is_same_user() now
+returns FALSE if we compare two credentials structures that are both
+invalid. This seems like reasonable, conservative behaviour: if we cannot
+prove that they are the same user, we should assume they are not.
+
+(Dropped new translatable string when backporting to `glib-2-62`.)
+
+Signed-off-by: Simon McVittie <smcv@collabora.com>
+---
+ gio/gcredentials.c | 42 +++++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 39 insertions(+), 3 deletions(-)
+
+diff --git a/gio/gcredentials.c b/gio/gcredentials.c
+index 57a39f2a2..ff9b7e0b8 100644
+--- a/gio/gcredentials.c
++++ b/gio/gcredentials.c
+@@ -265,6 +265,35 @@ g_credentials_to_string (GCredentials *credentials)
+ 
+ /* ---------------------------------------------------------------------------------------------------- */
+ 
++#if G_CREDENTIALS_USE_LINUX_UCRED
++/*
++ * Check whether @native contains invalid data. If getsockopt SO_PEERCRED
++ * is used on a TCP socket, it succeeds but yields a credentials structure
++ * with pid 0, uid -1 and gid -1. Similarly, if SO_PASSCRED is used on a
++ * receiving Unix socket when the sending socket did not also enable
++ * SO_PASSCRED, it can succeed but yield a credentials structure with
++ * pid 0, uid /proc/sys/kernel/overflowuid and gid
++ * /proc/sys/kernel/overflowgid.
++ */
++static gboolean
++linux_ucred_check_valid (struct ucred  *native,
++                         GError       **error)
++{
++  if (native->pid == 0
++      || native->uid == -1
++      || native->gid == -1)
++    {
++      g_set_error_literal (error,
++                           G_IO_ERROR,
++                           G_IO_ERROR_INVALID_DATA,
++                           "GCredentials contains invalid data");
++      return FALSE;
++    }
++
++  return TRUE;
++}
++#endif
++
+ /**
+  * g_credentials_is_same_user:
+  * @credentials: A #GCredentials.
+@@ -294,7 +323,8 @@ g_credentials_is_same_user (GCredentials  *credentials,
+ 
+   ret = FALSE;
+ #if G_CREDENTIALS_USE_LINUX_UCRED
+-  if (credentials->native.uid == other_credentials->native.uid)
++  if (linux_ucred_check_valid (&credentials->native, NULL)
++      && credentials->native.uid == other_credentials->native.uid)
+     ret = TRUE;
+ #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
+   if (credentials->native.cmcred_euid == other_credentials->native.cmcred_euid)
+@@ -453,7 +483,10 @@ g_credentials_get_unix_user (GCredentials    *credentials,
+   g_return_val_if_fail (error == NULL || *error == NULL, -1);
+ 
+ #if G_CREDENTIALS_USE_LINUX_UCRED
+-  ret = credentials->native.uid;
++  if (linux_ucred_check_valid (&credentials->native, error))
++    ret = credentials->native.uid;
++  else
++    ret = -1;
+ #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
+   ret = credentials->native.cmcred_euid;
+ #elif G_CREDENTIALS_USE_NETBSD_UNPCBID
+@@ -499,7 +532,10 @@ g_credentials_get_unix_pid (GCredentials    *credentials,
+   g_return_val_if_fail (error == NULL || *error == NULL, -1);
+ 
+ #if G_CREDENTIALS_USE_LINUX_UCRED
+-  ret = credentials->native.pid;
++  if (linux_ucred_check_valid (&credentials->native, error))
++    ret = credentials->native.pid;
++  else
++    ret = -1;
+ #elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
+   ret = credentials->native.cmcred_pid;
+ #elif G_CREDENTIALS_USE_NETBSD_UNPCBID
+-- 
+2.20.1
+
+
+From c7618cce3752e1f3681f75d0a26c7e07c15bd6a2 Mon Sep 17 00:00:00 2001
+From: Simon McVittie <smcv@collabora.com>
+Date: Mon, 14 Oct 2019 08:47:39 +0100
+Subject: [PATCH 3/3] GDBus: prefer getsockopt()-style credentials-passing APIs
+
+Closes: https://gitlab.gnome.org/GNOME/glib/issues/1831
+---
+ gio/gcredentialsprivate.h | 18 ++++++++++++++++++
+ gio/gdbusauth.c           | 27 +++++++++++++++++++++++++--
+ 2 files changed, 43 insertions(+), 2 deletions(-)
+
+diff --git a/gio/gcredentialsprivate.h b/gio/gcredentialsprivate.h
+index 06f0aed19..e9ec09b9f 100644
+--- a/gio/gcredentialsprivate.h
++++ b/gio/gcredentialsprivate.h
+@@ -81,6 +81,18 @@
+  */
+ #undef G_CREDENTIALS_SPOOFING_SUPPORTED
+ 
++/*
++ * G_CREDENTIALS_PREFER_MESSAGE_PASSING:
++ *
++ * Defined to 1 if the data structure transferred by the message-passing
++ * API is strictly more informative than the one transferred by the
++ * `getsockopt()`-style API, and hence should be preferred, even for
++ * protocols like D-Bus that are defined in terms of the credentials of
++ * the (process that opened the) socket, as opposed to the credentials
++ * of an individual message.
++ */
++#undef G_CREDENTIALS_PREFER_MESSAGE_PASSING
++
+ #ifdef __linux__
+ #define G_CREDENTIALS_SUPPORTED 1
+ #define G_CREDENTIALS_USE_LINUX_UCRED 1
+@@ -100,6 +112,12 @@
+ #define G_CREDENTIALS_NATIVE_SIZE (sizeof (struct cmsgcred))
+ #define G_CREDENTIALS_UNIX_CREDENTIALS_MESSAGE_SUPPORTED 1
+ #define G_CREDENTIALS_SPOOFING_SUPPORTED 1
++/* GLib doesn't implement it yet, but FreeBSD's getsockopt()-style API
++ * is getpeereid(), which is not as informative as struct cmsgcred -
++ * it does not tell us the PID. As a result, libdbus prefers to use
++ * SCM_CREDS, and if we implement getpeereid() in future, we should
++ * do the same. */
++#define G_CREDENTIALS_PREFER_MESSAGE_PASSING 1
+ 
+ #elif defined(__NetBSD__)
+ #define G_CREDENTIALS_SUPPORTED 1
+diff --git a/gio/gdbusauth.c b/gio/gdbusauth.c
+index 752ec23fc..14cc5d70e 100644
+--- a/gio/gdbusauth.c
++++ b/gio/gdbusauth.c
+@@ -31,6 +31,7 @@
+ #include "gdbusutils.h"
+ #include "gioenumtypes.h"
+ #include "gcredentials.h"
++#include "gcredentialsprivate.h"
+ #include "gdbusprivate.h"
+ #include "giostream.h"
+ #include "gdatainputstream.h"
+@@ -969,9 +970,31 @@ _g_dbus_auth_run_server (GDBusAuth              *auth,
+ 
+   g_data_input_stream_set_newline_type (dis, G_DATA_STREAM_NEWLINE_TYPE_CR_LF);
+ 
+-  /* first read the NUL-byte */
++  /* read the NUL-byte, possibly with credentials attached */
+ #ifdef G_OS_UNIX
+-  if (G_IS_UNIX_CONNECTION (auth->priv->stream))
++#ifndef G_CREDENTIALS_PREFER_MESSAGE_PASSING
++  if (G_IS_SOCKET_CONNECTION (auth->priv->stream))
++    {
++      GSocket *sock = g_socket_connection_get_socket (G_SOCKET_CONNECTION (auth->priv->stream));
++
++      local_error = NULL;
++      credentials = g_socket_get_credentials (sock, &local_error);
++
++      if (credentials == NULL && !g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
++        {
++          g_propagate_error (error, local_error);
++          goto out;
++        }
++      else
++        {
++          /* Clear the error indicator, so we can retry with
++           * g_unix_connection_receive_credentials() if necessary */
++          g_clear_error (&local_error);
++        }
++    }
++#endif
++
++  if (credentials == NULL && G_IS_UNIX_CONNECTION (auth->priv->stream))
+     {
+       local_error = NULL;
+       credentials = g_unix_connection_receive_credentials (G_UNIX_CONNECTION (auth->priv->stream),
+-- 
+2.20.1
+

diff --git a/dev-libs/glib/files/CVE-2020-6750.patch b/dev-libs/glib/files/CVE-2020-6750.patch
new file mode 100644
index 0000000..fe39914
--- /dev/null
+++ b/dev-libs/glib/files/CVE-2020-6750.patch
@@ -0,0 +1,763 @@
+From cc3cf6b8b2ad12d54f3474113f0ccfa7dcf66b7b Mon Sep 17 00:00:00 2001
+From: Michael Catanzaro <mcatanzaro@gnome.org>
+Date: Sat, 4 Jan 2020 20:46:25 -0600
+Subject: [PATCH] gsocketclient: run timeout source on the task's main context
+
+This shouldn't make any difference, because this code should only ever
+be running in the main context that was thread-default at the time the
+task was created, so it should already match the task's context. But
+let's make sure, just in case.
+---
+ gio/gsocketclient.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gio/gsocketclient.c b/gio/gsocketclient.c
+index 6adeee299..81721795b 100644
+--- a/gio/gsocketclient.c
++++ b/gio/gsocketclient.c
+@@ -1794,7 +1794,7 @@ g_socket_client_enumerator_callback (GObject      *object,
+   attempt->connection = (GIOStream *)g_socket_connection_factory_create_connection (socket);
+   attempt->timeout_source = g_timeout_source_new (HAPPY_EYEBALLS_CONNECTION_ATTEMPT_TIMEOUT_MS);
+   g_source_set_callback (attempt->timeout_source, on_connection_attempt_timeout, attempt, NULL);
+-  g_source_attach (attempt->timeout_source, g_main_context_get_thread_default ());
++  g_source_attach (attempt->timeout_source, g_task_get_context (data->task));
+   data->connection_attempts = g_slist_append (data->connection_attempts, attempt);
+ 
+   if (g_task_get_cancellable (data->task))
+-- 
+2.24.1
+
+From d4fcf91460696b09bb2b55c352a023f6dd71c7fe Mon Sep 17 00:00:00 2001
+From: Patrick Griffis <tingping@tingping.se>
+Date: Thu, 23 Jan 2020 19:58:41 -0800
+Subject: [PATCH] Refactor g_socket_client_connect_async()
+
+This is a fairly large refactoring. The highlights are:
+
+- Removing in-progress connections/addresses from GSocketClientAsyncConnectData:
+
+  This caused issues where multiple ConnectionAttempt's would step over eachother
+  and modify shared state causing bugs like accidentally bypassing a set proxy.
+
+  Fixes #1871
+  Fixes #1989
+  Fixes #1902
+
+- Cancelling address enumeration on error/completion
+
+- Queuing successful TCP connections and doing application layer work serially:
+
+  This is more in the spirit of Happy Eyeballs but it also greatly simplifies
+  the flow of connection handling so fewer tasks are happening in parallel
+  when they don't need to be.
+
+  The behavior also should more closely match that of g_socket_client_connect().
+
+- Better track the state of address enumeration:
+
+  Previously we were over eager to treat enumeration finishing as an error.
+
+  Fixes #1872
+  See also #1982
+
+- Add more detailed documentation and logging.
+
+Closes #1995
+---
+ gio/gsocketclient.c | 459 ++++++++++++++++++++++++++++----------------
+ 1 file changed, 296 insertions(+), 163 deletions(-)
+
+diff --git a/gio/gsocketclient.c b/gio/gsocketclient.c
+index 81721795b..c9943309c 100644
+--- a/gio/gsocketclient.c
++++ b/gio/gsocketclient.c
+@@ -1337,13 +1337,15 @@ typedef struct
+ 
+   GSocketConnectable *connectable;
+   GSocketAddressEnumerator *enumerator;
+-  GProxyAddress *proxy_addr;
+-  GSocket *socket;
+-  GIOStream *connection;
++  GCancellable *enumeration_cancellable;
+ 
+   GSList *connection_attempts;
++  GSList *successful_connections;
+   GError *last_error;
+ 
++  gboolean enumerated_at_least_once;
++  gboolean enumeration_completed;
++  gboolean connection_in_progress;
+   gboolean completed;
+ } GSocketClientAsyncConnectData;
+ 
+@@ -1355,10 +1357,9 @@ g_socket_client_async_connect_data_free (GSocketClientAsyncConnectData *data)
+   data->task = NULL;
+   g_clear_object (&data->connectable);
+   g_clear_object (&data->enumerator);
+-  g_clear_object (&data->proxy_addr);
+-  g_clear_object (&data->socket);
+-  g_clear_object (&data->connection);
++  g_clear_object (&data->enumeration_cancellable);
+   g_slist_free_full (data->connection_attempts, connection_attempt_unref);
++  g_slist_free_full (data->successful_connections, connection_attempt_unref);
+ 
+   g_clear_error (&data->last_error);
+ 
+@@ -1370,6 +1371,7 @@ typedef struct
+   GSocketAddress *address;
+   GSocket *socket;
+   GIOStream *connection;
++  GProxyAddress *proxy_addr;
+   GSocketClientAsyncConnectData *data; /* unowned */
+   GSource *timeout_source;
+   GCancellable *cancellable;
+@@ -1401,6 +1403,7 @@ connection_attempt_unref (gpointer pointer)
+       g_clear_object (&attempt->socket);
+       g_clear_object (&attempt->connection);
+       g_clear_object (&attempt->cancellable);
++      g_clear_object (&attempt->proxy_addr);
+       if (attempt->timeout_source)
+         {
+           g_source_destroy (attempt->timeout_source);
+@@ -1418,37 +1421,59 @@ connection_attempt_remove (ConnectionAttempt *attempt)
+ }
+ 
+ static void
+-g_socket_client_async_connect_complete (GSocketClientAsyncConnectData *data)
++cancel_all_attempts (GSocketClientAsyncConnectData *data)
+ {
+-  g_assert (data->connection);
++  GSList *l;
+ 
+-  if (!G_IS_SOCKET_CONNECTION (data->connection))
++  for (l = data->connection_attempts; l; l = g_slist_next (l))
+     {
+-      GSocketConnection *wrapper_connection;
+-
+-      wrapper_connection = g_tcp_wrapper_connection_new (data->connection, data->socket);
+-      g_object_unref (data->connection);
+-      data->connection = (GIOStream *)wrapper_connection;
++      ConnectionAttempt *attempt_entry = l->data;
++      g_cancellable_cancel (attempt_entry->cancellable);
++      connection_attempt_unref (attempt_entry);
+     }
++  g_slist_free (data->connection_attempts);
++  data->connection_attempts = NULL;
+ 
+-  if (!data->completed)
++  g_slist_free_full (data->successful_connections, connection_attempt_unref);
++  data->successful_connections = NULL;
++
++  g_cancellable_cancel (data->enumeration_cancellable);
++}
++
++static void
++g_socket_client_async_connect_complete (ConnectionAttempt *attempt)
++{
++  GSocketClientAsyncConnectData *data = attempt->data;
++  GError *error = NULL;
++  g_assert (attempt->connection);
++  g_assert (!data->completed);
++
++  if (!G_IS_SOCKET_CONNECTION (attempt->connection))
+     {
+-      GError *error = NULL;
++      GSocketConnection *wrapper_connection;
+ 
+-      if (g_cancellable_set_error_if_cancelled (g_task_get_cancellable (data->task), &error))
+-        {
+-          g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_COMPLETE, data->connectable, NULL);
+-          g_task_return_error (data->task, g_steal_pointer (&error));
+-        }
+-      else
+-        {
+-          g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_COMPLETE, data->connectable, data->connection);
+-          g_task_return_pointer (data->task, g_steal_pointer (&data->connection), g_object_unref);
+-        }
++      wrapper_connection = g_tcp_wrapper_connection_new (attempt->connection, attempt->socket);
++      g_object_unref (attempt->connection);
++      attempt->connection = (GIOStream *)wrapper_connection;
++    }
+ 
+-      data->completed = TRUE;
++  data->completed = TRUE;
++  cancel_all_attempts (data);
++
++  if (g_cancellable_set_error_if_cancelled (g_task_get_cancellable (data->task), &error))
++    {
++      g_debug ("GSocketClient: Connection cancelled!");
++      g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_COMPLETE, data->connectable, NULL);
++      g_task_return_error (data->task, g_steal_pointer (&error));
++    }
++  else
++    {
++      g_debug ("GSocketClient: Connection successful!");
++      g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_COMPLETE, data->connectable, attempt->connection);
++      g_task_return_pointer (data->task, g_steal_pointer (&attempt->connection), g_object_unref);
+     }
+ 
++  connection_attempt_unref (attempt);
+   g_object_unref (data->task);
+ }
+ 
+@@ -1470,59 +1495,63 @@ static void
+ enumerator_next_async (GSocketClientAsyncConnectData *data,
+                        gboolean                       add_task_ref)
+ {
+-  /* We need to cleanup the state */
+-  g_clear_object (&data->socket);
+-  g_clear_object (&data->proxy_addr);
+-  g_clear_object (&data->connection);
+-
+   /* Each enumeration takes a ref. This arg just avoids repeated unrefs when
+      an enumeration starts another enumeration */
+   if (add_task_ref)
+     g_object_ref (data->task);
+ 
+   g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_RESOLVING, data->connectable, NULL);
++  g_debug ("GSocketClient: Starting new address enumeration");
+   g_socket_address_enumerator_next_async (data->enumerator,
+-					  g_task_get_cancellable (data->task),
++					  data->enumeration_cancellable,
+ 					  g_socket_client_enumerator_callback,
+ 					  data);
+ }
+ 
++static void try_next_connection_or_finish (GSocketClientAsyncConnectData *, gboolean);
++
+ static void
+ g_socket_client_tls_handshake_callback (GObject      *object,
+ 					GAsyncResult *result,
+ 					gpointer      user_data)
+ {
+-  GSocketClientAsyncConnectData *data = user_data;
++  ConnectionAttempt *attempt = user_data;
++  GSocketClientAsyncConnectData *data = attempt->data;
+ 
+   if (g_tls_connection_handshake_finish (G_TLS_CONNECTION (object),
+ 					 result,
+ 					 &data->last_error))
+     {
+-      g_object_unref (data->connection);
+-      data->connection = G_IO_STREAM (object);
++      g_object_unref (attempt->connection);
++      attempt->connection = G_IO_STREAM (object);
+ 
+-      g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_TLS_HANDSHAKED, data->connectable, data->connection);
+-      g_socket_client_async_connect_complete (data);
++      g_debug ("GSocketClient: TLS handshake succeeded");
++      g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_TLS_HANDSHAKED, data->connectable, attempt->connection);
++      g_socket_client_async_connect_complete (attempt);
+     }
+   else
+     {
+       g_object_unref (object);
+-      enumerator_next_async (data, FALSE);
++      connection_attempt_unref (attempt);
++      g_debug ("GSocketClient: TLS handshake failed: %s", data->last_error->message);
++      try_next_connection_or_finish (data, TRUE);
+     }
+ }
+ 
+ static void
+-g_socket_client_tls_handshake (GSocketClientAsyncConnectData *data)
++g_socket_client_tls_handshake (ConnectionAttempt *attempt)
+ {
++  GSocketClientAsyncConnectData *data = attempt->data;
+   GIOStream *tlsconn;
+ 
+   if (!data->client->priv->tls)
+     {
+-      g_socket_client_async_connect_complete (data);
++      g_socket_client_async_connect_complete (attempt);
+       return;
+     }
+ 
+-  tlsconn = g_tls_client_connection_new (data->connection,
++  g_debug ("GSocketClient: Starting TLS handshake");
++  tlsconn = g_tls_client_connection_new (attempt->connection,
+ 					 data->connectable,
+ 					 &data->last_error);
+   if (tlsconn)
+@@ -1534,11 +1563,12 @@ g_socket_client_tls_handshake (GSocketClientAsyncConnectData *data)
+ 					G_PRIORITY_DEFAULT,
+ 					g_task_get_cancellable (data->task),
+ 					g_socket_client_tls_handshake_callback,
+-					data);
++					attempt);
+     }
+   else
+     {
+-      enumerator_next_async (data, FALSE);
++      connection_attempt_unref (attempt);
++      try_next_connection_or_finish (data, TRUE);
+     }
+ }
+ 
+@@ -1547,23 +1577,38 @@ g_socket_client_proxy_connect_callback (GObject      *object,
+ 					GAsyncResult *result,
+ 					gpointer      user_data)
+ {
+-  GSocketClientAsyncConnectData *data = user_data;
++  ConnectionAttempt *attempt = user_data;
++  GSocketClientAsyncConnectData *data = attempt->data;
+ 
+-  g_object_unref (data->connection);
+-  data->connection = g_proxy_connect_finish (G_PROXY (object),
+-					     result,
+-					     &data->last_error);
+-  if (data->connection)
++  g_object_unref (attempt->connection);
++  attempt->connection = g_proxy_connect_finish (G_PROXY (object),
++                                                result,
++                                                &data->last_error);
++  if (attempt->connection)
+     {
+-      g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_PROXY_NEGOTIATED, data->connectable, data->connection);
++      g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_PROXY_NEGOTIATED, data->connectable, attempt->connection);
+     }
+   else
+     {
+-      enumerator_next_async (data, FALSE);
++      connection_attempt_unref (attempt);
++      try_next_connection_or_finish (data, TRUE);
+       return;
+     }
+ 
+-  g_socket_client_tls_handshake (data);
++  g_socket_client_tls_handshake (attempt);
++}
++
++static void
++complete_connection_with_error (GSocketClientAsyncConnectData *data,
++                                GError                        *error)
++{
++  g_debug ("GSocketClient: Connection failed: %s", error->message);
++  g_assert (!data->completed);
++
++  g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_COMPLETE, data->connectable, NULL);
++  data->completed = TRUE;
++  cancel_all_attempts (data);
++  g_task_return_error (data->task, error);
+ }
+ 
+ static gboolean
+@@ -1577,15 +1622,114 @@ task_completed_or_cancelled (GSocketClientAsyncConnectData *data)
+     return TRUE;
+   else if (g_cancellable_set_error_if_cancelled (cancellable, &error))
+     {
+-      g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_COMPLETE, data->connectable, NULL);
+-      g_task_return_error (task, g_steal_pointer (&error));
+-      data->completed = TRUE;
++      complete_connection_with_error (data, g_steal_pointer (&error));
+       return TRUE;
+     }
+   else
+     return FALSE;
+ }
+ 
++static gboolean
++try_next_successful_connection (GSocketClientAsyncConnectData *data)
++{
++  ConnectionAttempt *attempt;
++  const gchar *protocol;
++  GProxy *proxy;
++
++  if (data->connection_in_progress)
++    return FALSE;
++
++  g_assert (data->successful_connections != NULL);
++  attempt = data->successful_connections->data;
++  g_assert (attempt != NULL);
++  data->successful_connections = g_slist_remove (data->successful_connections, attempt);
++  data->connection_in_progress = TRUE;
++
++  g_debug ("GSocketClient: Starting application layer connection");
++
++  if (!attempt->proxy_addr)
++    {
++      g_socket_client_tls_handshake (g_steal_pointer (&attempt));
++      return TRUE;
++    }
++
++  protocol = g_proxy_address_get_protocol (attempt->proxy_addr);
++
++  /* The connection should not be anything other than TCP,
++   * but let's put a safety guard in case
++   */
++  if (!G_IS_TCP_CONNECTION (attempt->connection))
++    {
++      g_critical ("Trying to proxy over non-TCP connection, this is "
++          "most likely a bug in GLib IO library.");
++
++      g_set_error_literal (&data->last_error,
++          G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
++          _("Proxying over a non-TCP connection is not supported."));
++    }
++  else if (g_hash_table_contains (data->client->priv->app_proxies, protocol))
++    {
++      /* Simply complete the connection, we don't want to do TLS handshake
++       * as the application proxy handling may need proxy handshake first */
++      g_socket_client_async_connect_complete (g_steal_pointer (&attempt));
++      return TRUE;
++    }
++  else if ((proxy = g_proxy_get_default_for_protocol (protocol)))
++    {
++      GIOStream *connection = attempt->connection;
++      GProxyAddress *proxy_addr = attempt->proxy_addr;
++
++      g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_PROXY_NEGOTIATING, data->connectable, attempt->connection);
++      g_debug ("GSocketClient: Starting proxy connection");
++      g_proxy_connect_async (proxy,
++                             connection,
++                             proxy_addr,
++                             g_task_get_cancellable (data->task),
++                             g_socket_client_proxy_connect_callback,
++                             g_steal_pointer (&attempt));
++      g_object_unref (proxy);
++      return TRUE;
++    }
++  else
++    {
++      g_clear_error (&data->last_error);
++
++      g_set_error (&data->last_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
++          _("Proxy protocol “%s” is not supported."),
++          protocol);
++    }
++
++  data->connection_in_progress = FALSE;
++  g_clear_pointer (&attempt, connection_attempt_unref);
++  return FALSE; /* All non-return paths are failures */
++}
++
++static void
++try_next_connection_or_finish (GSocketClientAsyncConnectData *data,
++                               gboolean                       end_current_connection)
++{
++  if (end_current_connection)
++    data->connection_in_progress = FALSE;
++
++  if (data->connection_in_progress)
++    return;
++
++  /* Keep trying successful connections until one works, each iteration pops one */
++  while (data->successful_connections)
++    {
++      if (try_next_successful_connection (data))
++        return;
++    }
++
++  if (!data->enumeration_completed)
++    {
++      enumerator_next_async (data, FALSE);
++      return;
++    }
++
++  complete_connection_with_error (data, data->last_error);
++}
++
+ static void
+ g_socket_client_connected_callback (GObject      *source,
+ 				    GAsyncResult *result,
+@@ -1593,10 +1737,7 @@ g_socket_client_connected_callback (GObject      *source,
+ {
+   ConnectionAttempt *attempt = user_data;
+   GSocketClientAsyncConnectData *data = attempt->data;
+-  GSList *l;
+   GError *error = NULL;
+-  GProxy *proxy;
+-  const gchar *protocol;
+ 
+   if (task_completed_or_cancelled (data) || g_cancellable_is_cancelled (attempt->cancellable))
+     {
+@@ -1618,11 +1759,12 @@ g_socket_client_connected_callback (GObject      *source,
+         {
+           clarify_connect_error (error, data->connectable, attempt->address);
+           set_last_error (data, error);
++          g_debug ("GSocketClient: Connection attempt failed: %s", error->message);
+           connection_attempt_remove (attempt);
+-          enumerator_next_async (data, FALSE);
+           connection_attempt_unref (attempt);
++          try_next_connection_or_finish (data, FALSE);
+         }
+-      else
++      else /* Silently ignore cancelled attempts */
+         {
+           g_clear_error (&error);
+           g_object_unref (data->task);
+@@ -1632,74 +1774,21 @@ g_socket_client_connected_callback (GObject      *source,
+       return;
+     }
+ 
+-  data->socket = g_steal_pointer (&attempt->socket);
+-  data->connection = g_steal_pointer (&attempt->connection);
+-
+-  for (l = data->connection_attempts; l; l = g_slist_next (l))
+-    {
+-      ConnectionAttempt *attempt_entry = l->data;
+-      g_cancellable_cancel (attempt_entry->cancellable);
+-      connection_attempt_unref (attempt_entry);
+-    }
+-  g_slist_free (data->connection_attempts);
+-  data->connection_attempts = NULL;
+-  connection_attempt_unref (attempt);
+-
+-  g_socket_connection_set_cached_remote_address ((GSocketConnection*)data->connection, NULL);
+-  g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_CONNECTED, data->connectable, data->connection);
++  g_socket_connection_set_cached_remote_address ((GSocketConnection*)attempt->connection, NULL);
++  g_debug ("GSocketClient: TCP connection successful");
++  g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_CONNECTED, data->connectable, attempt->connection);
+ 
+   /* wrong, but backward compatible */
+-  g_socket_set_blocking (data->socket, TRUE);
++  g_socket_set_blocking (attempt->socket, TRUE);
+ 
+-  if (!data->proxy_addr)
+-    {
+-      g_socket_client_tls_handshake (data);
+-      return;
+-    }
+-
+-  protocol = g_proxy_address_get_protocol (data->proxy_addr);
+-
+-  /* The connection should not be anything other than TCP,
+-   * but let's put a safety guard in case
++  /* This ends the parallel "happy eyeballs" portion of connecting.
++     Now that we have a successful tcp connection we will attempt to connect
++     at the TLS/Proxy layer. If those layers fail we will move on to the next
++     connection.
+    */
+-  if (!G_IS_TCP_CONNECTION (data->connection))
+-    {
+-      g_critical ("Trying to proxy over non-TCP connection, this is "
+-          "most likely a bug in GLib IO library.");
+-
+-      g_set_error_literal (&data->last_error,
+-          G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+-          _("Proxying over a non-TCP connection is not supported."));
+-
+-      enumerator_next_async (data, FALSE);
+-    }
+-  else if (g_hash_table_contains (data->client->priv->app_proxies, protocol))
+-    {
+-      /* Simply complete the connection, we don't want to do TLS handshake
+-       * as the application proxy handling may need proxy handshake first */
+-      g_socket_client_async_connect_complete (data);
+-    }
+-  else if ((proxy = g_proxy_get_default_for_protocol (protocol)))
+-    {
+-      g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_PROXY_NEGOTIATING, data->connectable, data->connection);
+-      g_proxy_connect_async (proxy,
+-                             data->connection,
+-                             data->proxy_addr,
+-                             g_task_get_cancellable (data->task),
+-                             g_socket_client_proxy_connect_callback,
+-                             data);
+-      g_object_unref (proxy);
+-    }
+-  else
+-    {
+-      g_clear_error (&data->last_error);
+-
+-      g_set_error (&data->last_error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+-          _("Proxy protocol “%s” is not supported."),
+-          protocol);
+-
+-      enumerator_next_async (data, FALSE);
+-    }
++  connection_attempt_remove (attempt);
++  data->successful_connections = g_slist_append (data->successful_connections, g_steal_pointer (&attempt));
++  try_next_connection_or_finish (data, FALSE);
+ }
+ 
+ static gboolean
+@@ -1707,7 +1796,11 @@ on_connection_attempt_timeout (gpointer data)
+ {
+   ConnectionAttempt *attempt = data;
+ 
+-  enumerator_next_async (attempt->data, TRUE);
++  if (!attempt->data->enumeration_completed)
++    {
++      g_debug ("GSocketClient: Timeout reached, trying another enumeration");
++      enumerator_next_async (attempt->data, TRUE);
++    }
+ 
+   g_clear_pointer (&attempt->timeout_source, g_source_unref);
+   return G_SOURCE_REMOVE;
+@@ -1717,9 +1810,9 @@ static void
+ on_connection_cancelled (GCancellable *cancellable,
+                          gpointer      data)
+ {
+-  GCancellable *attempt_cancellable = data;
++  GCancellable *linked_cancellable = G_CANCELLABLE (data);
+ 
+-  g_cancellable_cancel (attempt_cancellable);
++  g_cancellable_cancel (linked_cancellable);
+ }
+ 
+ static void
+@@ -1743,39 +1836,49 @@ g_socket_client_enumerator_callback (GObject      *object,
+ 						     result, &error);
+   if (address == NULL)
+     {
+-      if (data->connection_attempts)
++      if (G_UNLIKELY (data->enumeration_completed))
++        return;
++
++      data->enumeration_completed = TRUE;
++      g_debug ("GSocketClient: Address enumeration completed (out of addresses)");
++
++      /* As per API docs: We only care about error if its the first call,
++         after that the enumerator is done.
++
++         Note that we don't care about cancellation errors because
++         task_completed_or_cancelled() above should handle that.
++
++         If this fails and nothing is in progress then we will complete task here.
++       */
++      if ((data->enumerated_at_least_once && !data->connection_attempts && !data->connection_in_progress) ||
++          !data->enumerated_at_least_once)
+         {
+-          g_object_unref (data->task);
+-          return;
++          g_debug ("GSocketClient: Address enumeration failed: %s", error ? error->message : NULL);
++          if (data->last_error)
++            {
++              g_clear_error (&error);
++              error = data->last_error;
++              data->last_error = NULL;
++            }
++          else if (!error)
++            {
++              g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
++                _("Unknown error on connect"));
++            }
++
++          complete_connection_with_error (data, error);
+         }
+ 
+-      g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_COMPLETE, data->connectable, NULL);
+-      data->completed = TRUE;
+-      if (!error)
+-	{
+-	  if (data->last_error)
+-	    {
+-	      error = data->last_error;
+-	      data->last_error = NULL;
+-	    }
+-	  else
+-	    {
+-	      g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
+-				   _("Unknown error on connect"));
+-	    }
+-	}
+-      g_task_return_error (data->task, error);
++      /* Enumeration should never trigger again, drop our ref */
+       g_object_unref (data->task);
+       return;
+     }
+ 
++  data->enumerated_at_least_once = TRUE;
++  g_debug ("GSocketClient: Address enumeration succeeded");
+   g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_RESOLVED,
+ 			      data->connectable, NULL);
+ 
+-  if (G_IS_PROXY_ADDRESS (address) &&
+-      data->client->priv->enable_proxy)
+-    data->proxy_addr = g_object_ref (G_PROXY_ADDRESS (address));
+-
+   g_clear_error (&data->last_error);
+ 
+   socket = create_socket (data->client, address, &data->last_error);
+@@ -1793,6 +1896,10 @@ g_socket_client_enumerator_callback (GObject      *object,
+   attempt->cancellable = g_cancellable_new ();
+   attempt->connection = (GIOStream *)g_socket_connection_factory_create_connection (socket);
+   attempt->timeout_source = g_timeout_source_new (HAPPY_EYEBALLS_CONNECTION_ATTEMPT_TIMEOUT_MS);
++
++  if (G_IS_PROXY_ADDRESS (address) && data->client->priv->enable_proxy)
++    attempt->proxy_addr = g_object_ref (G_PROXY_ADDRESS (address));
++
+   g_source_set_callback (attempt->timeout_source, on_connection_attempt_timeout, attempt, NULL);
+   g_source_attach (attempt->timeout_source, g_task_get_context (data->task));
+   data->connection_attempts = g_slist_append (data->connection_attempts, attempt);
+@@ -1802,6 +1909,7 @@ g_socket_client_enumerator_callback (GObject      *object,
+                            g_object_ref (attempt->cancellable), g_object_unref);
+ 
+   g_socket_connection_set_cached_remote_address ((GSocketConnection *)attempt->connection, address);
++  g_debug ("GSocketClient: Starting TCP connection attempt");
+   g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_CONNECTING, data->connectable, attempt->connection);
+   g_socket_connection_connect_async (G_SOCKET_CONNECTION (attempt->connection),
+ 				     address,
+@@ -1854,24 +1962,48 @@ g_socket_client_connect_async (GSocketClient       *client,
+   else
+     data->enumerator = g_socket_connectable_enumerate (connectable);
+ 
+-  /* The flow and ownership here isn't quite obvious:
+-    - The task starts an async attempt to connect.
+-      - Each attempt holds a single ref on task.
+-      - Each attempt may create new attempts by timing out (not a failure) so
+-        there are multiple attempts happening in parallel.
+-      - Upon failure an attempt will start a new attempt that steals its ref
+-        until there are no more attempts left and it drops its ref.
+-      - Upon success it will cancel all other attempts and continue on
+-        to the rest of the connection (tls, proxies, etc) which do not
+-        happen in parallel and at the very end drop its ref.
+-      - Upon cancellation an attempt drops its ref.
+-   */
++  /* This function tries to match the behavior of g_socket_client_connect ()
++     which is simple enough but much of it is done in parallel to be as responsive
++     as possible as per Happy Eyeballs (RFC 8305). This complicates flow quite a
++     bit but we can describe it in 3 sections:
++
++     Firstly we have address enumeration (DNS):
++       - This may be triggered multiple times by enumerator_next_async().
++       - It also has its own cancellable (data->enumeration_cancellable).
++       - Enumeration is done lazily because GNetworkAddressAddressEnumerator
++         also does work in parallel and may lazily add new addresses.
++       - If the first enumeration errors then the task errors. Otherwise all enumerations
++         will potentially be used (until task or enumeration is cancelled).
++
++      Then we start attempting connections (TCP):
++        - Each connection is independent and kept in a ConnectionAttempt object.
++          - They each hold a ref on the main task and have their own cancellable.
++        - Multiple attempts may happen in parallel as per Happy Eyeballs.
++        - Upon failure or timeouts more connection attempts are made.
++          - If no connections succeed the task errors.
++        - Upon success they are kept in a list of successful connections.
++
++      Lastly we connect at the application layer (TLS, Proxies):
++        - These are done in serial.
++          - The reasoning here is that Happy Eyeballs is about making bad connections responsive
++            at the IP/TCP layers. Issues at the application layer are generally not due to
++            connectivity issues but rather misconfiguration.
++        - Upon failure it will try the next TCP connection until it runs out and
++          the task errors.
++        - Upon success it cancels everything remaining (enumeration and connections)
++          and returns the connection.
++  */
+ 
+   data->task = g_task_new (client, cancellable, callback, user_data);
+   g_task_set_check_cancellable (data->task, FALSE); /* We handle this manually */
+   g_task_set_source_tag (data->task, g_socket_client_connect_async);
+   g_task_set_task_data (data->task, data, (GDestroyNotify)g_socket_client_async_connect_data_free);
+ 
++  data->enumeration_cancellable = g_cancellable_new ();
++  if (cancellable)
++    g_cancellable_connect (cancellable, G_CALLBACK (on_connection_cancelled),
++                           g_object_ref (data->enumeration_cancellable), g_object_unref);
++
+   enumerator_next_async (data, FALSE);
+ }
+ 
+@@ -1990,6 +2122,7 @@ g_socket_client_connect_to_uri_async (GSocketClient        *client,
+     }
+   else
+     {
++      g_debug("g_socket_client_connect_to_uri_async");
+       g_socket_client_connect_async (client,
+ 				     connectable, cancellable,
+ 				     callback, user_data);
+-- 
+2.24.1
+

diff --git a/dev-libs/glib/glib-2.60.7-r2.ebuild b/dev-libs/glib/glib-2.60.7-r2.ebuild
new file mode 100644
index 0000000..986947b
--- /dev/null
+++ b/dev-libs/glib/glib-2.60.7-r2.ebuild
@@ -0,0 +1,283 @@
+# Copyright 1999-2020 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=7
+PYTHON_COMPAT=( python{3_6,3_7} )
+
+inherit flag-o-matic gnome.org gnome2-utils linux-info meson multilib multilib-minimal python-any-r1 toolchain-funcs xdg
+
+DESCRIPTION="The GLib library of C routines"
+HOMEPAGE="https://www.gtk.org/"
+
+LICENSE="LGPL-2.1+"
+SLOT="2"
+IUSE="dbus debug elibc_glibc fam gtk-doc kernel_linux +mime selinux static-libs systemtap test utils xattr"
+RESTRICT="!test? ( test )"
+
+KEYWORDS="amd64 arm arm64 ~mips ppc ppc64 x86"
+
+# * libelf isn't strictly necessary, but makes gresource tool more useful, and
+# the check is automagic in gio/meson.build. gresource is not a multilib tool
+# right now, thus it doesn't matter if non-native ABI libelf exists or not
+# (non-native binary is overwritten, it doesn't matter if libelf was linked to).
+# * Technically static-libs is needed on zlib, util-linux and perhaps more, but
+# these are used by GIO, which glib[static-libs] consumers don't really seem
+# to need at all, thus not imposing the deps for now and once some consumers
+# are actually found to static link libgio-2.0.a, we can revisit and either add
+# them or just put the (build) deps in that rare consumer instead of recursive
+# RDEPEND here (due to lack of recursive DEPEND).
+RDEPEND="
+	!<dev-util/gdbus-codegen-${PV}
+	>=virtual/libiconv-0-r1[${MULTILIB_USEDEP}]
+	>=dev-libs/libpcre-8.31:3[${MULTILIB_USEDEP},static-libs?]
+	>=virtual/libffi-3.0.13-r1:=[${MULTILIB_USEDEP}]
+	>=sys-libs/zlib-1.2.8-r1[${MULTILIB_USEDEP}]
+	>=virtual/libintl-0-r2[${MULTILIB_USEDEP}]
+	kernel_linux? ( >=sys-apps/util-linux-2.23[${MULTILIB_USEDEP}] )
+	selinux? ( >=sys-libs/libselinux-2.2.2-r5[${MULTILIB_USEDEP}] )
+	xattr? ( !elibc_glibc? ( >=sys-apps/attr-2.4.47-r1[${MULTILIB_USEDEP}] ) )
+	virtual/libelf:0=
+	fam? ( >=virtual/fam-0-r1[${MULTILIB_USEDEP}] )
+"
+DEPEND="${RDEPEND}"
+# libxml2 used for optional tests that get automatically skipped
+BDEPEND="
+	app-text/docbook-xsl-stylesheets
+	dev-libs/libxslt
+	>=sys-devel/gettext-0.19.8
+	gtk-doc? ( >=dev-util/gtk-doc-1.20
+		app-text/docbook-xml-dtd:4.2
+		app-text/docbook-xml-dtd:4.5 )
+	systemtap? ( >=dev-util/systemtap-1.3 )
+	${PYTHON_DEPS}
+	test? ( >=sys-apps/dbus-1.2.14 )
+	virtual/pkgconfig[${MULTILIB_USEDEP}]
+"
+# TODO: >=dev-util/gdbus-codegen-${PV} test dep once we modify gio/tests/meson.build to use external gdbus-codegen
+
+PDEPEND="
+	dbus? ( gnome-base/dconf )
+	mime? ( x11-misc/shared-mime-info )
+"
+# shared-mime-info needed for gio/xdgmime, bug #409481
+# dconf is needed to be able to save settings, bug #498436
+
+MULTILIB_CHOST_TOOLS=(
+	/usr/bin/gio-querymodules$(get_exeext)
+)
+
+pkg_setup() {
+	if use kernel_linux ; then
+		CONFIG_CHECK="~INOTIFY_USER"
+		if use test ; then
+			CONFIG_CHECK="~IPV6"
+			WARNING_IPV6="Your kernel needs IPV6 support for running some tests, skipping them."
+		fi
+		linux-info_pkg_setup
+	fi
+	python-any-r1_pkg_setup
+}
+
+src_prepare() {
+	eapply "${FILESDIR}"/${PV}-gdbus-fixes.patch #700538, included in 2.62.3+
+	eapply "${FILESDIR}"/CVE-2020-6750.patch
+	# Musl fix
+	eapply "${FILESDIR}/2.56.2-quark_init_on_demand.patch"
+	eapply "${FILESDIR}/2.56.2-gobject_init_on_demand.patch"
+
+	if use test; then
+		# TODO: Review the test exclusions, especially now with meson
+		# Disable tests requiring dev-util/desktop-file-utils when not installed, bug #286629, upstream bug #629163
+		if ! has_version dev-util/desktop-file-utils ; then
+			ewarn "Some tests will be skipped due dev-util/desktop-file-utils not being present on your system,"
+			ewarn "think on installing it to get these tests run."
+			sed -i -e "/appinfo\/associations/d" gio/tests/appinfo.c || die
+			sed -i -e "/g_test_add_func/d" gio/tests/desktop-app-info.c || die
+		fi
+
+		# gdesktopappinfo requires existing terminal (gnome-terminal or any
+		# other), falling back to xterm if one doesn't exist
+		#if ! has_version x11-terms/xterm && ! has_version x11-terms/gnome-terminal ; then
+		#	ewarn "Some tests will be skipped due to missing terminal program"
+		# These tests seem to sometimes fail even with a terminal; skip for now and reevulate with meson
+		# Also try https://gitlab.gnome.org/GNOME/glib/issues/1601 once ready for backport (or in a bump) and file new issue if still fails
+		sed -i -e "/appinfo\/launch/d" gio/tests/appinfo.c || die
+		# desktop-app-info/launch* might fail similarly
+		sed -i -e "/desktop-app-info\/launch-as-manager/d" gio/tests/desktop-app-info.c || die
+		#fi
+
+		# https://bugzilla.gnome.org/show_bug.cgi?id=722604
+		sed -i -e "/timer\/stop/d" glib/tests/timer.c || die
+		sed -i -e "/timer\/basic/d" glib/tests/timer.c || die
+
+		ewarn "Tests for search-utils have been skipped"
+		sed -i -e "/search-utils/d" glib/tests/meson.build || die
+
+		# Play nice with network-sandbox, but this approach would defeat the purpose of the test
+		#sed -i -e "s/localhost/127.0.0.1/g" gio/tests/gsocketclient-slow.c || die
+	else
+		# Don't build tests, also prevents extra deps, bug #512022
+		sed -i -e '/subdir.*tests/d' {.,gio,glib}/meson.build || die
+	fi
+
+	# Don't build fuzzing binaries - not used
+	sed -i -e '/subdir.*fuzzing/d' meson.build || die
+
+	# gdbus-codegen is a separate package
+	sed -i -e 's/install.*true/install : false/g' gio/gdbus-2.0/codegen/meson.build || die
+	# Older than meson-0.50 doesn't know about install kwarg for configure_file; for that we need to remove the install_dir kwarg.
+	# Upstream will remove the install kwarg in a future version to require only meson-0.49.2 or newer, at which point the
+	# install_dir removal only should be kept.
+	sed -i -e '/install_dir/d' gio/gdbus-2.0/codegen/meson.build || die
+
+	# Same kind of meson-0.50 issue with some installed-tests files; will likely be fixed upstream soon
+	sed -i -e '/install_dir/d' gio/tests/meson.build || die
+
+	cat > "${T}/glib-test-ld-wrapper" <<-EOF
+		#!/usr/bin/env sh
+		exec \${LD:-ld} "\$@"
+	EOF
+	chmod a+x "${T}/glib-test-ld-wrapper" || die
+	sed -i -e "s|'ld'|'${T}/glib-test-ld-wrapper'|g" gio/tests/meson.build || die
+
+	xdg_src_prepare
+	gnome2_environment_reset
+	# TODO: python_name sedding for correct python shebang? Might be relevant mainly for glib-utils only
+}
+
+multilib_src_configure() {
+	if use debug; then
+		append-cflags -DG_ENABLE_DEBUG
+	else
+		append-cflags -DG_DISABLE_CAST_CHECKS # https://gitlab.gnome.org/GNOME/glib/issues/1833
+	fi
+
+	# TODO: figure a way to pass appropriate values for all cross properties that glib uses (search for get_cross_property)
+	#if tc-is-cross-compiler ; then
+		# https://bugzilla.gnome.org/show_bug.cgi?id=756473
+		# TODO-meson: This should be in meson cross file as 'growing_stack' property; and more, look at get_cross_property
+		#case ${CHOST} in
+		#hppa*|metag*) export glib_cv_stack_grows=yes ;;
+		#*)            export glib_cv_stack_grows=no ;;
+		#esac
+	#fi
+
+	local emesonargs=(
+		-Ddefault_library=$(usex static-libs both shared)
+		$(meson_feature selinux)
+		$(meson_use xattr)
+		-Dlibmount=true # only used if host_system == 'linux'
+		-Dinternal_pcre=false
+		-Dman=true
+		$(meson_use systemtap dtrace)
+		$(meson_use systemtap)
+		-Dgtk_doc=$(multilib_native_usex gtk-doc true false)
+		$(meson_use fam)
+		-Dinstalled_tests=false
+		-Dnls=enabled
+	)
+	meson_src_configure
+}
+
+multilib_src_compile() {
+	meson_src_compile
+}
+
+multilib_src_test() {
+	export XDG_CONFIG_DIRS=/etc/xdg
+	export XDG_DATA_DIRS=/usr/local/share:/usr/share
+	export G_DBUS_COOKIE_SHA1_KEYRING_DIR="${T}/temp"
+	export LC_TIME=C # bug #411967
+	unset GSETTINGS_BACKEND # bug #596380
+	python_setup
+
+	# Related test is a bit nitpicking
+	mkdir "$G_DBUS_COOKIE_SHA1_KEYRING_DIR"
+	chmod 0700 "$G_DBUS_COOKIE_SHA1_KEYRING_DIR"
+
+	meson_src_test --timeout-multiplier 2 --no-suite flaky
+}
+
+multilib_src_install() {
+	meson_src_install
+	keepdir /usr/$(get_libdir)/gio/modules
+}
+
+multilib_src_install_all() {
+	einstalldocs
+
+	# These are installed by dev-util/glib-utils
+	# TODO: With patching we might be able to get rid of the python-any deps and removals, and test depend on glib-utils instead; revisit now with meson
+	rm "${ED}/usr/bin/glib-genmarshal" || die
+	rm "${ED}/usr/share/man/man1/glib-genmarshal.1" || die
+	rm "${ED}/usr/bin/glib-mkenums" || die
+	rm "${ED}/usr/share/man/man1/glib-mkenums.1" || die
+	rm "${ED}/usr/bin/gtester-report" || die
+	rm "${ED}/usr/share/man/man1/gtester-report.1" || die
+	# gdbus-codegen manpage installed by dev-util/gdbus-codegen
+	rm "${ED}/usr/share/man/man1/gdbus-codegen.1" || die
+}
+
+pkg_preinst() {
+	xdg_pkg_preinst
+
+	# Make gschemas.compiled belong to glib alone
+	local cache="/usr/share/glib-2.0/schemas/gschemas.compiled"
+
+	if [[ -e ${EROOT}${cache} ]]; then
+		cp "${EROOT}"${cache} "${ED}"/${cache} || die
+	else
+		touch "${ED}"${cache} || die
+	fi
+
+	multilib_pkg_preinst() {
+		# Make giomodule.cache belong to glib alone
+		local cache="/usr/$(get_libdir)/gio/modules/giomodule.cache"
+
+		if [[ -e ${EROOT}${cache} ]]; then
+			cp "${EROOT}"${cache} "${ED}"${cache} || die
+		else
+			touch "${ED}"${cache} || die
+		fi
+	}
+
+	# Don't run the cache ownership when cross-compiling, as it would end up with an empty cache
+	# file due to inability to create it and GIO might not look at any of the modules there
+	if ! tc-is-cross-compiler ; then
+		multilib_foreach_abi multilib_pkg_preinst
+	fi
+}
+
+pkg_postinst() {
+	xdg_pkg_postinst
+	# glib installs no schemas itself, but we force update for fresh install in case
+	# something has dropped in a schemas file without direct glib dep; and for upgrades
+	# in case the compiled schema format could have changed
+	gnome2_schemas_update
+
+	multilib_pkg_postinst() {
+		gnome2_giomodule_cache_update \
+			|| die "Update GIO modules cache failed (for ${ABI})"
+	}
+	if ! tc-is-cross-compiler ; then
+		multilib_foreach_abi multilib_pkg_postinst
+	else
+		ewarn "Updating of GIO modules cache skipped due to cross-compilation."
+		ewarn "You might want to run gio-querymodules manually on the target for"
+		ewarn "your final image for performance reasons and re-run it when packages"
+		ewarn "installing GIO modules get upgraded or added to the image."
+	fi
+}
+
+pkg_postrm() {
+	xdg_pkg_postrm
+	gnome2_schemas_update
+
+	if [[ -z ${REPLACED_BY_VERSION} ]]; then
+		multilib_pkg_postrm() {
+			rm -f "${EROOT}"/usr/$(get_libdir)/gio/modules/giomodule.cache
+		}
+		multilib_foreach_abi multilib_pkg_postrm
+		rm -f "${EROOT}"/usr/share/glib-2.0/schemas/gschemas.compiled
+	fi
+}


             reply	other threads:[~2020-02-26  5:11 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-02-26  5:11 Georgy Yakovlev [this message]
  -- strict thread matches above, loose matches on Subject: below --
2022-07-19 12:59 [gentoo-commits] proj/musl:master commit in: dev-libs/glib/files/, dev-libs/glib/ Anthony G. Basile
2020-09-21 22:34 Jory Pratt
2020-02-26  4:48 Georgy Yakovlev
2019-01-02 18:53 Anthony G. Basile
2018-08-18  9:51 Anthony G. Basile
2018-06-11  4:50 Aric Belsito
2017-09-03 20:54 Anthony G. Basile
2016-11-09 19:15 Aric Belsito

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1582693825.a0694d1160bd9b7a7cd9c95744487e0d45d1e87b.gyakovlev@gentoo \
    --to=gyakovlev@gentoo.org \
    --cc=gentoo-commits@lists.gentoo.org \
    --cc=gentoo-dev@lists.gentoo.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox