Hello community,
here is the log from the commit of package glib2 for openSUSE:Factory checked in at 2019-06-02 15:12:34
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/glib2 (Old)
and /work/SRC/openSUSE:Factory/.glib2.new.5148 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "glib2"
Sun Jun 2 15:12:34 2019 rev:210 rq:705579 version:2.60.3
Changes:
--------
--- /work/SRC/openSUSE:Factory/glib2/glib2.changes 2019-05-16 21:56:48.694868974 +0200
+++ /work/SRC/openSUSE:Factory/.glib2.new.5148/glib2.changes 2019-06-02 15:12:37.942175668 +0200
@@ -1,0 +2,22 @@
+Thu May 23 11:31:46 UTC 2019 - Dominique Leuenberger
+
+- Set umask to 022 before running glib-compile-schemas
+ (boo#1131761).
+
+-------------------------------------------------------------------
+Thu May 23 08:53:07 UTC 2019 - Dominique Leuenberger
+
+- Update to version 2.60.3:
+ + * Various fixes to small key/value support in `GHashTable`.
+ * Bugs fixed:
+ - Critical in g_socket_client_async_connect_complete.
+ - New GHashTable implementation confuses valgrind.
+ - test_month_names: assertion failed.
+ - GNetworkAddressAddressEnumerator unsafely modifies cache in
+ GNetworkAddress.
+ - Leaks in gsocketclient.c connection code.
+ - glib/date test fails.
+ - GDB pretty-printer for GHashTable no longer works
+ + Updated translations.
+
+-------------------------------------------------------------------
Old:
----
glib-2.60.2.tar.xz
New:
----
glib-2.60.3.tar.xz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ glib2.spec ++++++
--- /var/tmp/diff_new_pack.MCyZxB/_old 2019-06-02 15:12:38.562175400 +0200
+++ /var/tmp/diff_new_pack.MCyZxB/_new 2019-06-02 15:12:38.562175400 +0200
@@ -19,7 +19,7 @@
# systemtap is only offered as build-option, but not enabled, as it causes a build cycle
%bcond_with systemtap
Name: glib2
-Version: 2.60.2
+Version: 2.60.3
Release: 0
Summary: General-Purpose Utility Library
License: LGPL-2.1-or-later
@@ -176,10 +176,10 @@
%package -n libgio-2_0-0
Summary: A virtual file system library API
-Group: System/Libraries
# The tools are useful for people having libgio
# bnc#555605: shared-mime-info is required by libgio to properly detect mime types, but not during build
#!BuildIgnore: shared-mime-info
+Group: System/Libraries
Requires: %{name}-tools
# bnc#678518: libgio interacts with others by means of dbus-launch
Requires: dbus-launch
@@ -314,10 +314,26 @@
%fdupes %{buildroot}/%{_prefix}
%filetriggerin -n glib2-tools -- %{_datadir}/glib-2.0/schemas
+# Too many users complain about schemas compiled with wrong permissions
+# when in fact the system just honors there umask setting
+# Let's reset umask to 022 for glib-compile-schemas, then reset to
+# what the user had configured
+UMASK=$(umask)
+umask 022
%{_bindir}/glib-compile-schemas %{_datadir}/glib-2.0/schemas
+umask $UMASK
+unset UMASK
%filetriggerpostun -n glib2-tools -- %{_datadir}/glib-2.0/schemas
+# Too many users complain about schemas compiled with wrong permissions
+# when in fact the system just honors there umask setting
+# Let's reset umask to 022 for glib-compile-schemas, then reset to
+# what the user had configured
+UMASK=$(umask)
+umask 022
%{_bindir}/glib-compile-schemas %{_datadir}/glib-2.0/schemas
+umask $UMASK
+unset UMASK
%post -n libglib-2_0-0 -p /sbin/ldconfig
%post -n libgobject-2_0-0 -p /sbin/ldconfig
++++++ glib-2.60.2.tar.xz -> glib-2.60.3.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/glib-2.60.2/NEWS new/glib-2.60.3/NEWS
--- old/glib-2.60.2/NEWS 2019-05-03 15:43:28.000000000 +0200
+++ new/glib-2.60.3/NEWS 2019-05-21 17:59:04.000000000 +0200
@@ -1,3 +1,32 @@
+Overview of changes in GLib 2.60.3
+==================================
+
+* Various fixes to small key/value support in `GHashTable` (#1749, #1780)
+
+* Bugs fixed:
+ - #1747 Critical in g_socket_client_async_connect_complete
+ - #1749 New GHashTable implementation confuses valgrind
+ - #1759 test_month_names: assertion failed
+ - #1771 GNetworkAddressAddressEnumerator unsafely modifies cache in GNetworkAddress
+ - #1774 Leaks in gsocketclient.c connection code
+ - #1776 glib/date test fails
+ - #1780 GDB pretty-printer for GHashTable no longer works
+ - !815 Merge branch 'wip/tingping/socketclient-cancel-2' into 'master'
+ - !816 Backport !814 “gschema.dtd: Add target attribute to alias” to glib-2-60
+ - !826 Backport !824 “gsocketclient: Fix a leak in the connection code” to glib-2-60
+ - !829 Backport !828 “build: Fix a typo in the test whether _NL_ABALTMON_n is supported” to glib-2-60
+ - !834 Backport !823 "gnetworkaddress: Fix parallel enumerations interfering with eachother" to glib-2-60
+ - !838 Backport !835 “Fix typo in German translation” to glib-2-60
+ - !841 Backport !839 “tests: Update month name check for Greek locale” to glib-2-60
+ - !844 Backport !840 “ghash: Disable small-arrays under valgrind” to glib-2-60
+ - !846 Backport !845 “Fixing g_format_size_full() on Windows-x64” to glib-2-60
+ - !855 Backport !848 (more GHashTable fixes) to glib-2-60
+ - !858 Backport !852 “Update gdb pretty-printer for GHashTable” to glib-2-60
+
+* Translation updates:
+ - German
+
+
Overview of changes in GLib 2.60.2
==================================
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/glib-2.60.2/gio/gnetworkaddress.c new/glib-2.60.3/gio/gnetworkaddress.c
--- old/glib-2.60.2/gio/gnetworkaddress.c 2019-05-03 15:43:28.000000000 +0200
+++ new/glib-2.60.3/gio/gnetworkaddress.c 2019-05-21 17:59:05.000000000 +0200
@@ -52,6 +52,10 @@
* then attempt to connect to that host, handling the possibility of
* multiple IP addresses and multiple address families.
*
+ * The enumeration results of resolved addresses *may* be cached as long
+ * as this object is kept alive which may have unexpected results if
+ * alive for too long.
+ *
* See #GSocketConnectable for an example of using the connectable
* interface.
*/
@@ -66,7 +70,7 @@
struct _GNetworkAddressPrivate {
gchar *hostname;
guint16 port;
- GList *sockaddrs;
+ GList *cached_sockaddrs;
gchar *scheme;
gint64 resolver_serial;
@@ -105,7 +109,7 @@
g_free (addr->priv->hostname);
g_free (addr->priv->scheme);
- g_list_free_full (addr->priv->sockaddrs, g_object_unref);
+ g_list_free_full (addr->priv->cached_sockaddrs, g_object_unref);
G_OBJECT_CLASS (g_network_address_parent_class)->finalize (object);
}
@@ -220,30 +224,51 @@
}
-/*
- * g_network_address_add_addresses:
- * @addr: A #GNetworkAddress
- * @addresses: (transfer full): List of #GSocketAddress
- * @resolver_serial: Serial of #GResolver used
+/**
+ * inet_addresses_to_inet_socket_addresses:
+ * @addresses: (transfer full): #GList of #GInetAddress
*
- * Consumes address list and adds them to internal list.
+ * Returns: (transfer full): #GList of #GInetSocketAddress
*/
-static void
-g_network_address_add_addresses (GNetworkAddress *addr,
- GList *addresses,
- guint64 resolver_serial)
+static GList *
+inet_addresses_to_inet_socket_addresses (GNetworkAddress *addr,
+ GList *addresses)
{
- GList *a;
- GSocketAddress *sockaddr;
+ GList *a, *socket_addresses = NULL;
for (a = addresses; a; a = a->next)
{
- sockaddr = g_inet_socket_address_new (a->data, addr->priv->port);
- addr->priv->sockaddrs = g_list_append (addr->priv->sockaddrs, sockaddr);
+ GSocketAddress *sockaddr = g_inet_socket_address_new (a->data, addr->priv->port);
+ socket_addresses = g_list_append (socket_addresses, g_steal_pointer (&sockaddr));
g_object_unref (a->data);
}
+
g_list_free (addresses);
+ return socket_addresses;
+}
+/*
+ * g_network_address_set_cached_addresses:
+ * @addr: A #GNetworkAddress
+ * @addresses: (transfer full): List of #GInetAddress or #GInetSocketAddress
+ * @resolver_serial: Serial of #GResolver used
+ *
+ * Consumes @addresses and uses them to replace the current internal list.
+ */
+static void
+g_network_address_set_cached_addresses (GNetworkAddress *addr,
+ GList *addresses,
+ guint64 resolver_serial)
+{
+ g_assert (addresses != NULL);
+
+ if (addr->priv->cached_sockaddrs)
+ g_list_free_full (addr->priv->cached_sockaddrs, g_object_unref);
+
+ if (G_IS_INET_SOCKET_ADDRESS (addresses->data))
+ addr->priv->cached_sockaddrs = g_steal_pointer (&addresses);
+ else
+ addr->priv->cached_sockaddrs = inet_addresses_to_inet_socket_addresses (addr, g_steal_pointer (&addresses));
addr->priv->resolver_serial = resolver_serial;
}
@@ -252,11 +277,13 @@
{
GSocketAddress *sockaddr;
+ g_assert (addr->priv->cached_sockaddrs == NULL);
+
sockaddr = g_inet_socket_address_new_from_string (addr->priv->hostname,
addr->priv->port);
if (sockaddr)
{
- addr->priv->sockaddrs = g_list_append (addr->priv->sockaddrs, sockaddr);
+ addr->priv->cached_sockaddrs = g_list_append (addr->priv->cached_sockaddrs, sockaddr);
return TRUE;
}
else
@@ -325,7 +352,7 @@
addrs = g_list_append (addrs, g_inet_address_new_loopback (AF_INET6));
addrs = g_list_append (addrs, g_inet_address_new_loopback (AF_INET));
- g_network_address_add_addresses (addr, g_steal_pointer (&addrs), 0);
+ g_network_address_set_cached_addresses (addr, g_steal_pointer (&addrs), 0);
return G_SOCKET_CONNECTABLE (addr);
}
@@ -894,7 +921,6 @@
GNetworkAddress *addr; /* (owned) */
GList *addresses; /* (owned) (nullable) */
- GList *last_tail; /* (unowned) (nullable) */
GList *current_item; /* (unowned) (nullable) */
GTask *queued_task; /* (owned) (nullable) */
GTask *waiting_task; /* (owned) (nullable) */
@@ -927,8 +953,8 @@
g_clear_object (&addr_enum->waiting_task);
g_clear_error (&addr_enum->last_error);
g_object_unref (addr_enum->addr);
- g_clear_pointer (&addr_enum->addresses, g_list_free);
g_clear_pointer (&addr_enum->context, g_main_context_unref);
+ g_list_free_full (addr_enum->addresses, g_object_unref);
G_OBJECT_CLASS (_g_network_address_address_enumerator_parent_class)->finalize (object);
}
@@ -1014,16 +1040,19 @@
}
/* list_concat_interleaved:
- * @current_item: (transfer container): Already existing list
- * @new_list: (transfer none): New list to be interleaved and concatenated
+ * @parent_list: (transfer container): Already existing list
+ * @current_item: (transfer container): Item after which to resort
+ * @new_list: (transfer container): New list to be interleaved and concatenated
*
* This differs from g_list_concat() + list_copy_interleaved() in that it sorts
- * items in the previous list starting from @current_item.
+ * items in the previous list starting from @current_item and concats the results
+ * to @parent_list.
*
* Returns: (transfer container): New start of list
*/
static GList *
-list_concat_interleaved (GList *current_item,
+list_concat_interleaved (GList *parent_list,
+ GList *current_item,
GList *new_list)
{
GList *ipv4 = NULL, *ipv6 = NULL, *interleaved, *trailing = NULL;
@@ -1040,6 +1069,7 @@
list_split_families (trailing, &ipv4, &ipv6);
list_split_families (new_list, &ipv4, &ipv6);
+ g_list_free (new_list);
if (trailing)
g_list_free (trailing);
@@ -1049,7 +1079,73 @@
else
interleaved = list_interleave_families (ipv4, ipv6);
- return g_list_concat (current_item, interleaved);
+ return g_list_concat (parent_list, interleaved);
+}
+
+static void
+maybe_update_address_cache (GNetworkAddressAddressEnumerator *addr_enum,
+ GResolver *resolver)
+{
+ GList *addresses, *p;
+
+ /* Only cache complete results */
+ if (addr_enum->state & RESOLVE_STATE_WAITING_ON_IPV4 || addr_enum->state & RESOLVE_STATE_WAITING_ON_IPV6)
+ return;
+
+ /* The enumerators list will not necessarily be fully sorted */
+ addresses = list_copy_interleaved (addr_enum->addresses);
+ for (p = addresses; p; p = p->next)
+ g_object_ref (p->data);
+
+ g_network_address_set_cached_addresses (addr_enum->addr, g_steal_pointer (&addresses), g_resolver_get_serial (resolver));
+}
+
+static void
+g_network_address_address_enumerator_add_addresses (GNetworkAddressAddressEnumerator *addr_enum,
+ GList *addresses,
+ GResolver *resolver)
+{
+ GList *new_addresses = inet_addresses_to_inet_socket_addresses (addr_enum->addr, addresses);
+
+ if (addr_enum->addresses == NULL)
+ addr_enum->addresses = g_steal_pointer (&new_addresses);
+ else
+ addr_enum->addresses = list_concat_interleaved (addr_enum->addresses, addr_enum->current_item, g_steal_pointer (&new_addresses));
+
+ maybe_update_address_cache (addr_enum, resolver);
+}
+
+static gpointer
+copy_object (gconstpointer src,
+ gpointer user_data)
+{
+ return g_object_ref (G_OBJECT (src));
+}
+
+static GSocketAddress *
+init_and_query_next_address (GNetworkAddressAddressEnumerator *addr_enum)
+{
+ GList *next_item;
+
+ if (addr_enum->addresses == NULL)
+ addr_enum->addresses = g_list_copy_deep (addr_enum->addr->priv->cached_sockaddrs,
+ copy_object, NULL);
+
+ /* We always want to look at the next item at call time to get the latest results.
+ That means that sometimes ->next is NULL this call but is valid next call.
+ */
+ if (addr_enum->current_item == NULL)
+ next_item = addr_enum->current_item = addr_enum->addresses;
+ else
+ next_item = g_list_next (addr_enum->current_item);
+
+ if (next_item)
+ {
+ addr_enum->current_item = next_item;
+ return g_object_ref (addr_enum->current_item->data);
+ }
+ else
+ return NULL;
}
static GSocketAddress *
@@ -1059,7 +1155,6 @@
{
GNetworkAddressAddressEnumerator *addr_enum =
G_NETWORK_ADDRESS_ADDRESS_ENUMERATOR (enumerator);
- GSocketAddress *sockaddr;
if (addr_enum->addresses == NULL)
{
@@ -1071,13 +1166,13 @@
addr->priv->resolver_serial != serial)
{
/* Resolver has reloaded, discard cached addresses */
- g_list_free_full (addr->priv->sockaddrs, g_object_unref);
- addr->priv->sockaddrs = NULL;
+ g_list_free_full (addr->priv->cached_sockaddrs, g_object_unref);
+ addr->priv->cached_sockaddrs = NULL;
}
- if (!addr->priv->sockaddrs)
+ if (!addr->priv->cached_sockaddrs)
g_network_address_parse_sockaddr (addr);
- if (!addr->priv->sockaddrs)
+ if (!addr->priv->cached_sockaddrs)
{
GList *addresses;
@@ -1090,62 +1185,13 @@
return NULL;
}
- g_network_address_add_addresses (addr, g_steal_pointer (&addresses), serial);
+ g_network_address_set_cached_addresses (addr, g_steal_pointer (&addresses), serial);
}
- addr_enum->current_item = addr_enum->addresses = list_copy_interleaved (addr->priv->sockaddrs);
- addr_enum->last_tail = g_list_last (addr->priv->sockaddrs);
g_object_unref (resolver);
}
- if (addr_enum->current_item == NULL)
- return NULL;
-
- sockaddr = addr_enum->current_item->data;
- addr_enum->current_item = g_list_next (addr_enum->current_item);
- return g_object_ref (sockaddr);
-}
-
-/*
- * Each enumeration lazily initializes the internal address list from the
- * master list. It does this since addresses come in asynchronously and
- * they need to be resorted into the list already in use.
- */
-static GSocketAddress *
-init_and_query_next_address (GNetworkAddressAddressEnumerator *addr_enum)
-{
- GNetworkAddress *addr = addr_enum->addr;
- GSocketAddress *sockaddr;
-
- if (addr_enum->addresses == NULL)
- {
- addr_enum->current_item = addr_enum->addresses = list_copy_interleaved (addr->priv->sockaddrs);
- addr_enum->last_tail = g_list_last (addr_enum->addr->priv->sockaddrs);
- if (addr_enum->current_item)
- sockaddr = g_object_ref (addr_enum->current_item->data);
- else
- sockaddr = NULL;
- }
- else
- {
- GList *parent_tail = g_list_last (addr_enum->addr->priv->sockaddrs);
-
- if (addr_enum->last_tail != parent_tail)
- {
- addr_enum->current_item = list_concat_interleaved (addr_enum->current_item, g_list_next (addr_enum->last_tail));
- addr_enum->last_tail = parent_tail;
- }
-
- if (addr_enum->current_item->next)
- {
- addr_enum->current_item = g_list_next (addr_enum->current_item);
- sockaddr = g_object_ref (addr_enum->current_item->data);
- }
- else
- sockaddr = NULL;
- }
-
- return sockaddr;
+ return init_and_query_next_address (addr_enum);
}
static void
@@ -1153,12 +1199,13 @@
GTask *task,
GError *error)
{
- GSocketAddress *sockaddr = init_and_query_next_address (addr_enum);
-
if (error)
g_task_return_error (task, error);
else
- g_task_return_pointer (task, sockaddr, g_object_unref);
+ {
+ GSocketAddress *sockaddr = init_and_query_next_address (addr_enum);
+ g_task_return_pointer (task, g_steal_pointer (&sockaddr), g_object_unref);
+ }
g_object_unref (task);
}
@@ -1197,13 +1244,7 @@
addresses = g_resolver_lookup_by_name_with_flags_finish (resolver, result, &error);
if (!error)
- {
- /* Regardless of which responds first we add them to the enumerator
- * which does mean the timing of next_async() will potentially change
- * the results */
- g_network_address_add_addresses (addr_enum->addr, g_steal_pointer (&addresses),
- g_resolver_get_serial (resolver));
- }
+ g_network_address_address_enumerator_add_addresses (addr_enum, g_steal_pointer (&addresses), resolver);
else
g_debug ("IPv6 DNS error: %s", error->message);
@@ -1264,10 +1305,7 @@
addresses = g_resolver_lookup_by_name_with_flags_finish (resolver, result, &error);
if (!error)
- {
- g_network_address_add_addresses (addr_enum->addr, g_steal_pointer (&addresses),
- g_resolver_get_serial (resolver));
- }
+ g_network_address_address_enumerator_add_addresses (addr_enum, g_steal_pointer (&addresses), resolver);
else
g_debug ("IPv4 DNS error: %s", error->message);
@@ -1331,11 +1369,11 @@
addr->priv->resolver_serial != serial)
{
/* Resolver has reloaded, discard cached addresses */
- g_list_free_full (addr->priv->sockaddrs, g_object_unref);
- addr->priv->sockaddrs = NULL;
+ g_list_free_full (addr->priv->cached_sockaddrs, g_object_unref);
+ addr->priv->cached_sockaddrs = NULL;
}
- if (addr->priv->sockaddrs == NULL)
+ if (addr->priv->cached_sockaddrs == NULL)
{
if (g_network_address_parse_sockaddr (addr))
complete_queued_task (addr_enum, task, NULL);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/glib-2.60.2/gio/gschema.dtd new/glib-2.60.3/gio/gschema.dtd
--- old/glib-2.60.2/gio/gschema.dtd 2019-05-03 15:43:28.000000000 +0200
+++ new/glib-2.60.3/gio/gschema.dtd 2019-05-21 17:59:05.000000000 +0200
@@ -62,7 +62,8 @@
<!ELEMENT aliases (alias+) >
<!-- each alias element specifies an alias for one of the possible values -->
<!ELEMENT alias EMPTY >
-<!ATTLIST alias value CDATA #REQUIRED >
+<!ATTLIST alias value CDATA #REQUIRED
+ target CDATA #REQUIRED >
<!ELEMENT child EMPTY >
<!ATTLIST child name CDATA #REQUIRED
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/glib-2.60.2/gio/gsocketclient.c new/glib-2.60.3/gio/gsocketclient.c
--- old/glib-2.60.2/gio/gsocketclient.c 2019-05-03 15:43:28.000000000 +0200
+++ new/glib-2.60.3/gio/gsocketclient.c 2019-05-21 17:59:05.000000000 +0200
@@ -1426,15 +1426,24 @@
data->connection = (GIOStream *)wrapper_connection;
}
- if (!g_task_return_error_if_cancelled (data->task))
+ if (!data->completed)
{
- 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);
+ GError *error = NULL;
+
+ 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);
+ }
+
+ data->completed = TRUE;
}
- else
- g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_COMPLETE, data->connectable, NULL);
- data->completed = TRUE;
g_object_unref (data->task);
}
@@ -1606,6 +1615,7 @@
set_last_error (data, error);
connection_attempt_remove (attempt);
enumerator_next_async (data, FALSE);
+ connection_attempt_unref (attempt);
}
else
{
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/glib-2.60.2/gio/tests/network-address.c new/glib-2.60.3/gio/tests/network-address.c
--- old/glib-2.60.2/gio/tests/network-address.c 2019-05-03 15:43:28.000000000 +0200
+++ new/glib-2.60.3/gio/tests/network-address.c 2019-05-21 17:59:05.000000000 +0200
@@ -426,7 +426,9 @@
} AsyncData;
static void
-got_addr (GObject *source_object, GAsyncResult *result, gpointer user_data)
+got_addr (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
{
GSocketAddressEnumerator *enumerator;
AsyncData *data;
@@ -466,6 +468,30 @@
}
static void
+got_addr_ignored (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GSocketAddressEnumerator *enumerator;
+ GSocketAddress *a; /* owned */
+ GError *error = NULL;
+
+ /* This function simply ignores the returned addresses but keeps enumerating */
+
+ enumerator = G_SOCKET_ADDRESS_ENUMERATOR (source_object);
+
+ a = g_socket_address_enumerator_next_finish (enumerator, result, &error);
+ g_assert_no_error (error);
+ if (a != NULL)
+ {
+ g_object_unref (a);
+ g_socket_address_enumerator_next_async (enumerator, NULL,
+ got_addr_ignored, user_data);
+ }
+}
+
+
+static void
test_loopback_async (void)
{
GSocketConnectable *addr; /* owned */
@@ -647,6 +673,39 @@
}
static void
+test_happy_eyeballs_parallel (HappyEyeballsFixture *fixture,
+ gconstpointer user_data)
+{
+ AsyncData data = { 0 };
+ GSocketAddressEnumerator *enumerator2;
+
+ enumerator2 = g_socket_connectable_enumerate (fixture->addr);
+
+ data.delay_ms = FAST_DELAY_LESS_THAN_TIMEOUT;
+ data.loop = fixture->loop;
+
+ /* We run multiple enumerations at once, the results shouldn't be affected. */
+
+ g_socket_address_enumerator_next_async (enumerator2, NULL, got_addr_ignored, &data);
+ g_socket_address_enumerator_next_async (fixture->enumerator, NULL, got_addr, &data);
+ g_main_loop_run (fixture->loop);
+
+ assert_list_matches_expected (data.addrs, fixture->input_all_results);
+
+ /* Run again to ensure the cache from the previous one is correct */
+
+ data.addrs = NULL;
+ g_object_unref (enumerator2);
+
+ enumerator2 = g_socket_connectable_enumerate (fixture->addr);
+ g_socket_address_enumerator_next_async (enumerator2, NULL, got_addr, &data);
+ g_main_loop_run (fixture->loop);
+
+ assert_list_matches_expected (data.addrs, fixture->input_all_results);
+ g_object_unref (enumerator2);
+}
+
+static void
test_happy_eyeballs_slow_ipv4 (HappyEyeballsFixture *fixture,
gconstpointer user_data)
{
@@ -958,6 +1017,8 @@
g_test_add ("/network-address/happy-eyeballs/basic", HappyEyeballsFixture, NULL,
happy_eyeballs_setup, test_happy_eyeballs_basic, happy_eyeballs_teardown);
+ g_test_add ("/network-address/happy-eyeballs/parallel", HappyEyeballsFixture, NULL,
+ happy_eyeballs_setup, test_happy_eyeballs_parallel, happy_eyeballs_teardown);
g_test_add ("/network-address/happy-eyeballs/slow-ipv4", HappyEyeballsFixture, NULL,
happy_eyeballs_setup, test_happy_eyeballs_slow_ipv4, happy_eyeballs_teardown);
g_test_add ("/network-address/happy-eyeballs/slow-ipv6", HappyEyeballsFixture, NULL,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/glib-2.60.2/glib/ghash.c new/glib-2.60.3/glib/ghash.c
--- old/glib-2.60.2/glib/ghash.c 2019-05-03 15:43:28.000000000 +0200
+++ new/glib-2.60.3/glib/ghash.c 2019-05-21 17:59:05.000000000 +0200
@@ -38,6 +38,7 @@
#include "gtestutils.h"
#include "gslice.h"
#include "grefcount.h"
+#include "gvalgrind.h"
/* The following #pragma is here so we can do this...
*
@@ -555,15 +556,58 @@
}
/*
+ * g_hash_table_setup_storage:
+ * @hash_table: our #GHashTable
+ *
+ * Initialise the hash table size, mask, mod, and arrays.
+ */
+static void
+g_hash_table_setup_storage (GHashTable *hash_table)
+{
+ gboolean small;
+
+ /* We want to use small arrays only if:
+ * - we are running on a system where that makes sense (64 bit); and
+ * - we are not running under valgrind.
+ */
+ small = FALSE;
+
+#ifdef USE_SMALL_ARRAYS
+ small = TRUE;
+
+# ifdef ENABLE_VALGRIND
+ if (RUNNING_ON_VALGRIND)
+ small = FALSE;
+# endif
+#endif
+
+ g_hash_table_set_shift (hash_table, HASH_TABLE_MIN_SHIFT);
+
+ hash_table->have_big_keys = !small;
+ hash_table->have_big_values = !small;
+
+ hash_table->keys = g_hash_table_realloc_key_or_value_array (NULL, hash_table->size, hash_table->have_big_keys);
+ hash_table->values = hash_table->keys;
+ hash_table->hashes = g_new0 (guint, hash_table->size);
+}
+
+/*
* g_hash_table_remove_all_nodes:
* @hash_table: our #GHashTable
* @notify: %TRUE if the destroy notify handlers are to be called
*
- * Removes all nodes from the table. Since this may be a precursor to
- * freeing the table entirely, no resize is performed.
+ * Removes all nodes from the table.
*
* If @notify is %TRUE then the destroy notify functions are called
* for the key and value of the hash node.
+ *
+ * Since this may be a precursor to freeing the table entirely, we'd
+ * ideally perform no resize, and we can indeed avoid that in some
+ * cases. However: in the case that we'll be making callbacks to user
+ * code (via destroy notifies) we need to consider that the user code
+ * might call back into the table again. In this case, we setup a new
+ * set of arrays so that any callers will see an empty (but valid)
+ * table.
*/
static void
g_hash_table_remove_all_nodes (GHashTable *hash_table,
@@ -577,6 +621,8 @@
gpointer *old_keys;
gpointer *old_values;
guint *old_hashes;
+ gboolean old_have_big_keys;
+ gboolean old_have_big_values;
/* If the hash table is already empty, there is nothing to be done. */
if (hash_table->nnodes == 0)
@@ -585,6 +631,7 @@
hash_table->nnodes = 0;
hash_table->noccupied = 0;
+ /* Easy case: no callbacks, so we just zero out the arrays */
if (!notify ||
(hash_table->key_destroy_func == NULL &&
hash_table->value_destroy_func == NULL))
@@ -605,43 +652,52 @@
return;
}
- /* Keep the old storage space around to iterate over it. */
+ /* Hard case: we need to do user callbacks. There are two
+ * possibilities here:
+ *
+ * 1) there are no outstanding references on the table and therefore
+ * nobody should be calling into it again (destroying == true)
+ *
+ * 2) there are outstanding references, and there may be future
+ * calls into the table, either after we return, or from the destroy
+ * notifies that we're about to do (destroying == false)
+ *
+ * We handle both cases by taking the current state of the table into
+ * local variables and replacing it with something else: in the "no
+ * outstanding references" cases we replace it with a bunch of
+ * null/zero values so that any access to the table will fail. In the
+ * "may receive future calls" case, we reinitialise the struct to
+ * appear like a newly-created empty table.
+ *
+ * In both cases, we take over the references for the current state,
+ * freeing them below.
+ */
old_size = hash_table->size;
- old_keys = hash_table->keys;
- old_values = hash_table->values;
- old_hashes = hash_table->hashes;
-
- /* Now create a new storage space; If the table is destroyed we can use the
- * shortcut of not creating a new storage. This saves the allocation at the
- * cost of not allowing any recursive access.
- * However, the application doesn't own any reference anymore, so access
- * is not allowed. If accesses are done, then either an assert or crash
- * *will* happen. */
- g_hash_table_set_shift (hash_table, HASH_TABLE_MIN_SHIFT);
+ old_have_big_keys = hash_table->have_big_keys;
+ old_have_big_values = hash_table->have_big_values;
+ old_keys = g_steal_pointer (&hash_table->keys);
+ old_values = g_steal_pointer (&hash_table->values);
+ old_hashes = g_steal_pointer (&hash_table->hashes);
+
if (!destruction)
- {
- hash_table->keys = g_hash_table_realloc_key_or_value_array (NULL, hash_table->size, FALSE);
- hash_table->values = hash_table->keys;
- hash_table->hashes = g_new0 (guint, hash_table->size);
- }
+ /* Any accesses will see an empty table */
+ g_hash_table_setup_storage (hash_table);
else
- {
- hash_table->keys = NULL;
- hash_table->values = NULL;
- hash_table->hashes = NULL;
- }
+ /* Will cause a quick crash on any attempted access */
+ hash_table->size = hash_table->mod = hash_table->mask = 0;
+ /* Now do the actual destroy notifies */
for (i = 0; i < old_size; i++)
{
if (HASH_IS_REAL (old_hashes[i]))
{
- key = g_hash_table_fetch_key_or_value (old_keys, i, hash_table->have_big_keys);
- value = g_hash_table_fetch_key_or_value (old_values, i, hash_table->have_big_values);
+ key = g_hash_table_fetch_key_or_value (old_keys, i, old_have_big_keys);
+ value = g_hash_table_fetch_key_or_value (old_values, i, old_have_big_values);
old_hashes[i] = UNUSED_HASH_VALUE;
- g_hash_table_assign_key_or_value (old_keys, i, hash_table->have_big_keys, NULL);
- g_hash_table_assign_key_or_value (old_values, i, hash_table->have_big_values, NULL);
+ g_hash_table_assign_key_or_value (old_keys, i, old_have_big_keys, NULL);
+ g_hash_table_assign_key_or_value (old_values, i, old_have_big_values, NULL);
if (hash_table->key_destroy_func != NULL)
hash_table->key_destroy_func (key);
@@ -651,9 +707,6 @@
}
}
- hash_table->have_big_keys = FALSE;
- hash_table->have_big_values = FALSE;
-
/* Destroy old storage space. */
if (old_keys != old_values)
g_free (old_values);
@@ -1016,7 +1069,6 @@
GHashTable *hash_table;
hash_table = g_slice_new (GHashTable);
- g_hash_table_set_shift (hash_table, HASH_TABLE_MIN_SHIFT);
g_atomic_ref_count_init (&hash_table->ref_count);
hash_table->nnodes = 0;
hash_table->noccupied = 0;
@@ -1027,17 +1079,8 @@
#endif
hash_table->key_destroy_func = key_destroy_func;
hash_table->value_destroy_func = value_destroy_func;
- hash_table->keys = g_hash_table_realloc_key_or_value_array (NULL, hash_table->size, FALSE);
- hash_table->values = hash_table->keys;
- hash_table->hashes = g_new0 (guint, hash_table->size);
-#ifdef USE_SMALL_ARRAYS
- hash_table->have_big_keys = FALSE;
- hash_table->have_big_values = FALSE;
-#else
- hash_table->have_big_keys = TRUE;
- hash_table->have_big_values = TRUE;
-#endif
+ g_hash_table_setup_storage (hash_table);
return hash_table;
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/glib-2.60.2/glib/glib_gdb.py new/glib-2.60.3/glib/glib_gdb.py
--- old/glib-2.60.2/glib/glib_gdb.py 2019-05-03 15:43:28.000000000 +0200
+++ new/glib-2.60.3/glib/glib_gdb.py 2019-05-21 17:59:05.000000000 +0200
@@ -86,11 +86,27 @@
"Prints a GHashTable"
class _iterator:
+ class _pointer_array:
+ def __init__(self, ptr, big_items):
+ self._big_items = big_items
+ self._gpointer_type = gdb.lookup_type("gpointer")
+ item_type = self._gpointer_type if self._big_items else gdb.lookup_type("guint")
+
+ self._items = ptr.cast(item_type.pointer())
+
+ def __getitem__(self, item):
+ item = self._items[item]
+
+ if not self._big_items:
+ item = item.cast(self._gpointer_type)
+
+ return item
+
def __init__(self, ht, keys_are_strings):
self.ht = ht
if ht != 0:
- self.keys = ht["keys"]
- self.values = ht["values"]
+ self.keys = self._pointer_array(ht["keys"], ht["have_big_keys"])
+ self.values = self._pointer_array(ht["values"], ht["have_big_values"])
self.hashes = ht["hashes"]
self.size = ht["size"]
self.pos = 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/glib-2.60.2/glib/gutils.c new/glib-2.60.3/glib/gutils.c
--- old/glib-2.60.2/glib/gutils.c 2019-05-03 15:43:28.000000000 +0200
+++ new/glib-2.60.3/glib/gutils.c 2019-05-21 17:59:05.000000000 +0200
@@ -2322,7 +2322,7 @@
struct Format
{
guint64 factor;
- char string[9];
+ char string[10];
};
typedef enum
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/glib-2.60.2/glib/tests/date.c new/glib-2.60.3/glib/tests/date.c
--- old/glib-2.60.2/glib/tests/date.c 2019-05-03 15:43:28.000000000 +0200
+++ new/glib-2.60.3/glib/tests/date.c 2019-05-21 17:59:05.000000000 +0200
@@ -388,7 +388,7 @@
TEST_DATE ( 1, 4, 2018, "%OB %Y", "Απρίλιος 2018");
TEST_DATE ( 1, 5, 2018, "%OB %Y", "Μάιος 2018");
TEST_DATE ( 1, 6, 2018, "%OB %Y", "Ιούνιος 2018");
- TEST_DATE (16, 7, 2018, "%e %b %Y", "16 Ιούλ 2018");
+ TEST_DATE (16, 7, 2018, "%e %b %Y", "16 Ιουλ 2018");
TEST_DATE ( 1, 8, 2018, "%Ob %Y", "Αύγ 2018");
}
else
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/glib-2.60.2/meson.build new/glib-2.60.3/meson.build
--- old/glib-2.60.2/meson.build 2019-05-03 15:43:28.000000000 +0200
+++ new/glib-2.60.3/meson.build 2019-05-21 17:59:05.000000000 +0200
@@ -1,5 +1,5 @@
project('glib', 'c', 'cpp',
- version : '2.60.2',
+ version : '2.60.3',
meson_version : '>= 0.48.0',
default_options : [
'buildtype=debugoptimized',
@@ -986,20 +986,20 @@
#include
int main (int argc, char ** argv) {
char *str;
- str = nl_langinfo (_NL_ALTMON_1);
- str = nl_langinfo (_NL_ALTMON_2);
- str = nl_langinfo (_NL_ALTMON_3);
- str = nl_langinfo (_NL_ALTMON_4);
- str = nl_langinfo (_NL_ALTMON_5);
- str = nl_langinfo (_NL_ALTMON_6);
- str = nl_langinfo (_NL_ALTMON_7);
- str = nl_langinfo (_NL_ALTMON_8);
- str = nl_langinfo (_NL_ALTMON_9);
- str = nl_langinfo (_NL_ALTMON_10);
- str = nl_langinfo (_NL_ALTMON_11);
- str = nl_langinfo (_NL_ALTMON_12);
+ str = nl_langinfo (_NL_ABALTMON_1);
+ str = nl_langinfo (_NL_ABALTMON_2);
+ str = nl_langinfo (_NL_ABALTMON_3);
+ str = nl_langinfo (_NL_ABALTMON_4);
+ str = nl_langinfo (_NL_ABALTMON_5);
+ str = nl_langinfo (_NL_ABALTMON_6);
+ str = nl_langinfo (_NL_ABALTMON_7);
+ str = nl_langinfo (_NL_ABALTMON_8);
+ str = nl_langinfo (_NL_ABALTMON_9);
+ str = nl_langinfo (_NL_ABALTMON_10);
+ str = nl_langinfo (_NL_ABALTMON_11);
+ str = nl_langinfo (_NL_ABALTMON_12);
return 0;
- }''', name : 'nl_langinfo (_NL_ALTMON_n)')
+ }''', name : 'nl_langinfo (_NL_ABALTMON_n)')
glib_conf.set('HAVE_LANGINFO_ABALTMON', 1)
endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/glib-2.60.2/po/de.po new/glib-2.60.3/po/de.po
--- old/glib-2.60.2/po/de.po 2019-05-03 15:43:28.000000000 +0200
+++ new/glib-2.60.3/po/de.po 2019-05-21 17:59:05.000000000 +0200
@@ -2719,7 +2719,7 @@
"desktop/” or “/system/” are deprecated."
msgstr ""
"Warnung: Schema »%s« hat den Pfad »%s«. Mit »/apps/«, »/desktop/« oder »/"
-"system/« beginnende Pfade gelten jecoh als veraltet."
+"system/« beginnende Pfade gelten jedoch als veraltet."
#: gio/glib-compile-schemas.c:1271
#, c-format