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 <[email protected]> + +- Set umask to 022 before running glib-compile-schemas + (boo#1131761). + +------------------------------------------------------------------- +Thu May 23 08:53:07 UTC 2019 - Dominique Leuenberger <[email protected]> + +- 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 <langinfo.h> 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
