diff --git a/NEWS b/NEWS
index 192c29dbfb..b0d897e6e5 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,24 @@
+Overview of changes in GLib 2.84.4, 2025-08-08
+==============================================
+
+* Bugs fixed:
+  - #3716 (CVE-2025-7039) (#YWH-PGM9867-104) Buffer Under-read on GLib through
+    glib/gfileutils.c via get_tmp_file() (Michael Catanzaro)
+  - #3721 GFile leak in g_local_file_set_display_name during error handling
+    (Philip Withnall, Michael Catanzaro)
+  - !4668 Backport !4667 “Incorrect output parameter handling in closure helper
+    of g_settings_bind_with_mapping_closures” to glib-2-84
+  - !4675 Backport !4674 “gfileutils: fix computation of temporary file name” to
+    glib-2-84
+  - !4679 Backport !4677 and !4678 “Fix GFile leak in
+    g_local_file_set_display_name()” to glib-2-84
+  - !4697 Backport !4696 “gthreadpool: Catch pool_spawner creation failure” to
+    glib-2-84
+  - !4705 Backport !4702 “gio/filenamecompleter: Fix leaks” to glib-2-84
+  - !4711 Backport !4708 “gfilenamecompleter: Fix g_object_unref() of undefined
+    value” to glib-2-84
+
+
 Overview of changes in GLib 2.84.3, 2025-06-13
 ==============================================
 
diff --git a/debian/changelog b/debian/changelog
index 7207a96974..982cbafac0 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,78 @@
+glib2.0 (2.84.4-3~deb13u1) trixie; urgency=medium
+
+  * Go back to debian/trixie branch for a stable update
+  * d/tests/manual/1065022.sh: Update manual test script used to reproduce
+    and test fixes for #1065022
+    - Adapt to upgrade from bookworm to trixie, rather than bookworm to sid
+    - Optionally reproduce #1110696 instead
+    - Optionally test the extra safety checks in the postrm
+    - Add a simpler mechanism to test proposed packages for either
+      bookworm or trixie
+    - Improve diagnostic output
+
+ -- Simon McVittie <smcv@debian.org>  Mon, 18 Aug 2025 09:30:17 +0100
+
+glib2.0 (2.84.4-3) unstable; urgency=medium
+
+  * d/control: Generate the intended Provides in libgirepository-2.0-0
+
+ -- Simon McVittie <smcv@debian.org>  Sun, 17 Aug 2025 17:30:44 +0100
+
+glib2.0 (2.84.4-2) unstable; urgency=medium
+
+  * Mention #1110640 in previous changelog entry
+  * libgirepository-2.0-0: Generate a dependency on a virtual package
+    for libffi-related symbols, to avoid trouble during future libffi ABI
+    transitions (Closes: #1110825)
+  * libglib2.0-0t64: Make maintainer scripts shellcheck-clean
+  * libglib2.0-0t64.postrm:
+    - Refactor to use functions that early-return if we do not want to
+      do the cleanup, avoiding stacking conditionals
+    - Don't remove cache files if they would be non-empty,
+      guarding against issues similar to #1065022 and #1110696
+      (mitigates: #1110696)
+  * libglib2.0-0t64.preinst: Disarm libglib2.0-0 postrm for all
+    architectures, avoiding a corner case where the faulty postrm that
+    suffered from #1065022 would still exist if it belonged to a former
+    foreign architecture that was already disabled, but libglib2.0-0
+    from that architecture was still in removed-but-not-purged state,
+    resulting in #1065022 recurring when that version of libglib2.0-0
+    was subsequently purged (Closes: #1110696)
+  * d/tests/1065022-futureproofing:
+    - Fix a test regression by generating a versioned Provides when
+      building a mockup of a hypothetical future libglib2.0-0xyz.
+      This regression wasn't immediately obvious because the autopkgtest
+      is marked as flaky (it depends on various implementation details
+      which we can't completely rely on).
+    - Make sure required packages stay installed, failing the test early
+      if their dependencies cannot be satisfied
+    - Produce only TAP output on stdout, and a diagnostic log on stderr
+    - Improve diagnostic output
+
+ -- Simon McVittie <smcv@debian.org>  Tue, 12 Aug 2025 10:01:06 +0100
+
+glib2.0 (2.84.4-1) unstable; urgency=medium
+
+  * d/control, d/gbp.conf: Use debian/forky packaging branch.
+    The debian/latest branch is now tracking 2.85.x for Debian
+    experimental.
+  * New upstream stable release
+    - Ensure that generating temporary file names does not access memory
+      outside the intended array of alphanumeric characters if a long-running
+      program generates billions of temporary file names
+      (CVE-2025-7039, glib#3716 upstream; believed to be unlikely to be
+      exploitable in practice. Closes: #1110640)
+    - Fix the intended ability for g_settings_bind_with_mapping_closures()
+      to copy a value to the destination object
+      (glib!4667 upstream)
+    - If creating a thread pool fails, report a recoverable error instead
+      of crashing with a fatal error
+      (glib#3712 upstream)
+    - Fix several memory leaks
+      (glib#3721, glib!4702 upstream)
+
+ -- Simon McVittie <smcv@debian.org>  Fri, 08 Aug 2025 19:13:23 +0100
+
 glib2.0 (2.84.3-1) unstable; urgency=medium
 
   * New upstream stable release
diff --git a/debian/clean b/debian/clean
index 550447d14b..c0ad4464ee 100644
--- a/debian/clean
+++ b/debian/clean
@@ -1,4 +1,6 @@
 debian/cross-tools/
+debian/extra-substvars
+debian/libgirepository-2.0-0.symbols
 debian/libglib2.0-0t64.triggers
 debian/meson/exe-wrapper.ini
 gio/gdbus-2.0/codegen/*.pyc
diff --git a/debian/control b/debian/control
index 22ecdabc83..59fe1e5c83 100644
--- a/debian/control
+++ b/debian/control
@@ -26,6 +26,7 @@ Build-Depends:
  linux-libc-dev [linux-any],
  meson (>= 1.4.0),
  pkgconf,
+ python3-debian:native,
  python3-docutils <!nodoc>,
  python3-packaging:native,
  python3:native,
@@ -51,7 +52,7 @@ Rules-Requires-Root: no
 Standards-Version: 4.7.0
 Homepage: https://gitlab.gnome.org/GNOME/glib
 Vcs-Browser: https://salsa.debian.org/gnome-team/glib
-Vcs-Git: https://salsa.debian.org/gnome-team/glib.git
+Vcs-Git: https://salsa.debian.org/gnome-team/glib.git -b debian/trixie
 
 Package: libglib2.0-0t64
 Replaces:
@@ -379,6 +380,8 @@ Multi-Arch: same
 Depends:
  ${misc:Depends},
  ${shlibs:Depends},
+Provides:
+ libgirepository-2.0-0-with-${local:libffiN} (= ${binary:Version}),
 Description: GLib runtime library for handling GObject introspection data
  GLib is a library containing many useful C routines for things such
  as trees, hashes, lists, and strings.  It is a useful general-purpose
diff --git a/debian/extra-substvars.py b/debian/extra-substvars.py
new file mode 100755
index 0000000000..d6b743b2a6
--- /dev/null
+++ b/debian/extra-substvars.py
@@ -0,0 +1,51 @@
+#!/usr/bin/python3
+# Copyright 2021 Simon McVittie
+# SPDX-License-Identifier: MIT
+
+'''
+Inspect libffi-dev:$DEB_HOST_ARCH and print the corresponding library ABI
+name, e.g. "local:libffiN=libffi8".
+'''
+
+import os
+import subprocess
+
+import debian.deb822
+
+if __name__ == '__main__':
+    deb_host_arch = os.environ['DEB_HOST_ARCH']
+
+    result = subprocess.run(
+        ['dpkg-query', '-s', 'libffi-dev:' + deb_host_arch],
+        stdout=subprocess.PIPE,
+        check=True,
+    )
+    stanza = result.stdout.decode('utf-8')      # type: ignore
+    fields = debian.deb822.Packages(stanza)
+
+    libffiN = ''
+
+    for dependency in fields.relations['depends']:
+        for alternative in dependency:
+            if (
+                alternative['name'].startswith('libffi')
+                and alternative['name'][6].isdigit()
+            ):
+                if libffiN != '':
+                    raise AssertionError(
+                        'More than one libffiN dependency in libffi-dev'
+                    )
+
+                libffiN = alternative['name']
+
+    if not libffiN:
+        raise AssertionError(
+            'No libffiN dependency in libffi-dev'
+        )
+
+    print('local:libffiN=' + libffiN)
+
+    for suffix in ('GNU_TYPE',):
+        var = 'DEB_HOST_' + suffix
+        substvar = var.replace('_', '-')
+        print(f'local:{substvar}={os.environ[var]}')
diff --git a/debian/gbp.conf b/debian/gbp.conf
index e5bd40a6df..61981bdf27 100644
--- a/debian/gbp.conf
+++ b/debian/gbp.conf
@@ -1,6 +1,6 @@
 [DEFAULT]
 pristine-tar = True
-debian-branch = debian/latest
+debian-branch = debian/trixie
 upstream-branch = upstream/2.84.x
 component = unicode-data
 
diff --git a/debian/libgirepository-2.0-0.symbols b/debian/libgirepository-2.0-0.symbols.in
similarity index 93%
rename from debian/libgirepository-2.0-0.symbols
rename to debian/libgirepository-2.0-0.symbols.in
index 4ade1aafd4..32fac9ad15 100644
--- a/debian/libgirepository-2.0-0.symbols
+++ b/debian/libgirepository-2.0-0.symbols.in
@@ -1,4 +1,7 @@
+# Dependency template 0: ordinary symbols
 libgirepository-2.0.so.0 libgirepository-2.0-0 #MINVER#
+# Dependency template 1: symbols whose meaning depends on libffi ABI
+| libgirepository-2.0-0 #MINVER#, libgirepository-2.0-0-with-@libffiN@ #MINVER#
 * Build-Depends-Package: libgirepository-2.0-dev
  gi_arg_info_get_closure_index@Base 2.79.2
  gi_arg_info_get_destroy_index@Base 2.79.2
@@ -26,12 +29,12 @@ libgirepository-2.0.so.0 libgirepository-2.0-0 #MINVER#
  gi_base_info_ref@Base 2.79.2
  gi_base_info_unref@Base 2.79.2
  gi_callable_info_can_throw_gerror@Base 2.79.2
- gi_callable_info_create_closure@Base 2.79.2
- gi_callable_info_destroy_closure@Base 2.79.2
+ gi_callable_info_create_closure@Base 2.79.2 1
+ gi_callable_info_destroy_closure@Base 2.79.2 1
  gi_callable_info_get_arg@Base 2.79.2
  gi_callable_info_get_async_function@Base 2.83.0
  gi_callable_info_get_caller_owns@Base 2.79.2
- gi_callable_info_get_closure_native_address@Base 2.79.2
+ gi_callable_info_get_closure_native_address@Base 2.79.2 1
  gi_callable_info_get_finish_function@Base 2.83.0
  gi_callable_info_get_instance_ownership_transfer@Base 2.79.2
  gi_callable_info_get_n_args@Base 2.79.2
@@ -74,9 +77,9 @@ libgirepository-2.0.so.0 libgirepository-2.0-0 #MINVER#
  gi_function_info_get_type@Base 2.79.2
  gi_function_info_get_vfunc@Base 2.79.2
  gi_function_info_invoke@Base 2.79.2
- gi_function_info_prep_invoker@Base 2.79.2
- gi_function_invoker_clear@Base 2.79.2
- gi_function_invoker_new_for_address@Base 2.79.2
+ gi_function_info_prep_invoker@Base 2.79.2 1
+ gi_function_invoker_clear@Base 2.79.2 1
+ gi_function_invoker_new_for_address@Base 2.79.2 1
  gi_interface_info_find_method@Base 2.79.2
  gi_interface_info_find_signal@Base 2.79.2
  gi_interface_info_find_vfunc@Base 2.79.2
@@ -186,11 +189,11 @@ libgirepository-2.0.so.0 libgirepository-2.0-0 #MINVER#
  gi_struct_info_is_foreign@Base 2.79.2
  gi_struct_info_is_gtype_struct@Base 2.79.2
  gi_type_info_argument_from_hash_pointer@Base 2.79.2
- gi_type_info_extract_ffi_return_value@Base 2.79.2
+ gi_type_info_extract_ffi_return_value@Base 2.79.2 1
  gi_type_info_get_array_fixed_size@Base 2.79.2
  gi_type_info_get_array_length_index@Base 2.79.2
  gi_type_info_get_array_type@Base 2.79.2
- gi_type_info_get_ffi_type@Base 2.79.2
+ gi_type_info_get_ffi_type@Base 2.79.2 1
  gi_type_info_get_interface@Base 2.79.2
  gi_type_info_get_param_type@Base 2.79.2
  gi_type_info_get_storage_type@Base 2.79.2
@@ -200,8 +203,8 @@ libgirepository-2.0.so.0 libgirepository-2.0-0 #MINVER#
  gi_type_info_is_pointer@Base 2.79.2
  gi_type_info_is_zero_terminated@Base 2.79.2
  gi_type_tag_argument_from_hash_pointer@Base 2.79.2
- gi_type_tag_extract_ffi_return_value@Base 2.79.2
- gi_type_tag_get_ffi_type@Base 2.79.2
+ gi_type_tag_extract_ffi_return_value@Base 2.79.2 1
+ gi_type_tag_get_ffi_type@Base 2.79.2 1
  gi_type_tag_hash_pointer_from_argument@Base 2.79.2
  gi_type_tag_to_string@Base 2.79.2
  gi_typelib_get_namespace@Base 2.79.2
diff --git a/debian/libglib2.0-0t64.postinst b/debian/libglib2.0-0t64.postinst
index d140c17646..0d9da799b6 100644
--- a/debian/libglib2.0-0t64.postinst
+++ b/debian/libglib2.0-0t64.postinst
@@ -1,13 +1,15 @@
 #!/bin/sh
+# Debian Policy §10.4 says /bin/sh has a superset of POSIX functionality
+# shellcheck disable=SC3043
+
 set -e
 
 
 handle_triggers () {
     local trigger
-    local dirs
 
     for trigger in "$@"; do
-        if ! [ -d $trigger ]; then
+        if ! [ -d "$trigger" ]; then
             continue
         fi
         case $trigger in
@@ -28,6 +30,8 @@ handle_triggers () {
 }
 
 if [ "$1" = triggered ]; then
+    # The list of triggers is space-separated, so word-splitting is intended:
+    # shellcheck disable=SC2086
     handle_triggers $2
     exit 0
 fi
diff --git a/debian/libglib2.0-0t64.postrm b/debian/libglib2.0-0t64.postrm
index 056e982134..e8f0819e0d 100644
--- a/debian/libglib2.0-0t64.postrm
+++ b/debian/libglib2.0-0t64.postrm
@@ -1,34 +1,87 @@
 #! /bin/sh
+# Debian Policy §10.4 says /bin/sh has a superset of POSIX functionality
+# shellcheck disable=SC3043
+
 set -e
 
 #DEBHELPER#
 
+clean_up_giomodule_cache ()
+{
+    local multiarch="#DEB_HOST_MULTIARCH#"
+    local modules="/usr/lib/${multiarch}/gio/modules"
+    local iter
+
+    if ! [ -d "$modules" ]; then
+        return 0
+    fi
+
+    # Don't remove giomodule.cache if libglib2.0-0t64 has been replaced
+    # by some other ABI variant of essentially the same library
+    # (for example libglib2.0-0xyz), if that ever happens, to
+    # avoid causing an equivalent of <https://bugs.debian.org/1065022>.
+    #
+    # This implementation is based on the assumption that any GLib
+    # version that still uses ${libdir}/gio/modules/giomodule.cache
+    # will also continue to ship ${libdir}/glib-2.0.
+    if [ -d "/usr/lib/${multiarch}/glib-2.0" ]; then
+        return 0
+    fi
+
+    # As an additional safety-catch, don't remove giomodule.cache if
+    # there is at least one module that should have been listed in it.
+    for iter in "$modules"/*.so; do
+        if [ -e "$iter" ]; then
+            echo "$0: not removing $modules/giomodule.cache because $iter still exists" >&2
+            return 0
+        fi
+    done
+
+    rm -f "$modules/giomodule.cache"
+    rmdir -p --ignore-fail-on-non-empty "$modules"
+}
+
+clean_up_gsettings_schemas ()
+{
+    local schemas="/usr/share/glib-2.0/schemas"
+    local iter
+
+    if ! [ -d "$schemas" ]; then
+        return 0
+    fi
+
+    # Similarly, instead of using $DPKG_MAINTSCRIPT_PACKAGE_REFCOUNT, only
+    # remove gschemas.compiled if GLib has completely gone away - not just
+    # libglib2.0-0 and libglib2.0-0t64, but any possible future ABI variant
+    # like libglib2.0-0xyz.
+    #
+    # This implementation is based on the assumption that any GLib
+    # version that still uses ${datadir}/glib-2.0/schemas
+    # will also continue to ship ${libdir}/glib-2.0.
+    for iter in /usr/lib/*/glib-2.0; do
+        if [ -e "$iter" ]; then
+            return 0
+        fi
+    done
+
+    # As an additional safety-catch, don't remove gschemas.compiled if
+    # there is at least one schema that should have been listed in it.
+    for iter in "$schemas"/*.xml; do
+        if [ -e "$iter" ]; then
+            echo "$0: not removing $schemas/gschemas.compiled because $iter still exists" >&2
+            return 0
+        fi
+    done
+
+    rm -f "$schemas/gschemas.compiled"
+    rmdir -p --ignore-fail-on-non-empty "$schemas"
+}
+
 case "$1" in
     (purge)
-        # Don't remove giomodule.cache if libglib2.0-0t64 has been replaced
-        # by some other ABI variant of essentially the same library
-        # (for example libglib2.0-0xyz), if that ever happens, to
-        # avoid causing an equivalent of <https://bugs.debian.org/1065022>.
-        #
-        # This implementation is based on the assumption that any GLib
-        # version that still uses ${libdir}/gio/modules/giomodule.cache
-        # will also continue to ship ${libdir}/glib-2.0.
-        if [ -d /usr/lib/#DEB_HOST_MULTIARCH#/gio/modules ] && ! [ -d "/usr/lib/#DEB_HOST_MULTIARCH#/glib-2.0" ]; then
-            rm -f /usr/lib/#DEB_HOST_MULTIARCH#/gio/modules/giomodule.cache
-            rmdir -p --ignore-fail-on-non-empty /usr/lib/#DEB_HOST_MULTIARCH#/gio/modules
-        fi
+        clean_up_giomodule_cache
+        clean_up_gsettings_schemas
         ;;
 esac
 
-# Similarly, instead of using $DPKG_MAINTSCRIPT_PACKAGE_REFCOUNT, only
-# remove gschemas.compiled if GLib has completely gone away - not just
-# libglib2.0-0 and libglib2.0-0t64, but any possible future ABI variant
-# like libglib2.0-0xyz.
-#
-# This implementation is based on the assumption that any GLib
-# version that still uses ${datadir}/glib-2.0/schemas
-# will also continue to ship ${libdir}/glib-2.0.
-if [ "$1" = purge ] && [ -d /usr/share/glib-2.0/schemas ] && [ "$(echo /usr/lib/*/glib-2.0)" = "/usr/lib/*/glib-2.0" ]; then
-    rm -f /usr/share/glib-2.0/schemas/gschemas.compiled
-    rmdir -p --ignore-fail-on-non-empty /usr/share/glib-2.0/schemas
-fi
+# vim:set sw=4 sts=4 et:
diff --git a/debian/libglib2.0-0t64.preinst b/debian/libglib2.0-0t64.preinst
index cd55739e43..f76c4f334b 100644
--- a/debian/libglib2.0-0t64.preinst
+++ b/debian/libglib2.0-0t64.preinst
@@ -13,12 +13,12 @@ set -e
 case "$1" in
     (install|upgrade)
         # Do this cleanup on upgrade from any version older than the one that
-        # introduced this change to experimental.
+        # addressed #1110696.
         #
         # We also need to do this cleanup on new installations of
         # libglib2.0-0t64 (because any new installation might be replacing
         # libglib2.0-0) so treat an empty version as being arbitrarily old.
-        if dpkg --compare-versions "${2:-}" lt "2.79.3-3"
+        if dpkg --compare-versions "${2:-}" lt "2.84.4-2~"
         then
             # If there are several multiarch instances, they might have been
             # removed but not purged, in which case purging them (perhaps
@@ -28,7 +28,12 @@ case "$1" in
             # only doing this cleanup for the current architecture, we attempt
             # to clean up all multiarch instances the first time any single
             # instance is installed or upgraded.
-            for arch in $(dpkg --print-architecture) $(dpkg --print-foreign-architectures)
+            # This originally used $(dpkg --print-architecture) and
+            # $(dpkg --print-foreign-architectures), but it is possible for
+            # libglib2.0-0:i386 to still exist in removed-but-not-purged
+            # state after an i386 foreign architecture has been disabled:
+            # see #1110696.
+            for arch in $(dpkg-query -W -f '${Architecture}\n' libglib2.0-0 2>/dev/null || true)
             do
                 if old_postrm=$(dpkg-query --control-path "libglib2.0-0:$arch" postrm 2>/dev/null) \
                     && [ -n "$old_postrm" ] \
diff --git a/debian/rules b/debian/rules
index 8e1fdc93ee..e0e42eba4f 100755
--- a/debian/rules
+++ b/debian/rules
@@ -62,6 +62,9 @@ maintainer-update-unicode-data:
 	rm -f glib/tests/casemap.txt
 	$(CURDIR)/tools/update-unicode-data.sh $(CURDIR)/unicode-data 16.0.0
 
+debian/extra-substvars:
+	dpkg-architecture -c debian/extra-substvars.py > debian/extra-substvars
+
 execute_before_dh_auto_configure: cross-tools
 
 cross_tools = \
@@ -407,7 +410,12 @@ execute_before_dh_installdeb-arch:
 		    > debian/libglib2.0-0t64.$$script ; \
 	done
 
-override_dh_gencontrol-arch:
-	dh_gencontrol -pgirepository-tools -- \
-		-Vlocal:DEB-HOST-GNU-TYPE=$(DEB_HOST_GNU_TYPE)
-	dh_gencontrol --remaining-packages
+debian/libgirepository-2.0-0.symbols: debian/libgirepository-2.0-0.symbols.in debian/extra-substvars
+	set -e; \
+	libffiN=$$(sed -ne 's/^local:libffiN=//p' debian/extra-substvars); \
+	sed -e "s/@libffiN@/$$libffiN/" < $< > $@
+
+execute_before_dh_makeshlibs: debian/libgirepository-2.0-0.symbols
+
+override_dh_gencontrol: debian/extra-substvars
+	dh_gencontrol -- -Tdebian/extra-substvars
diff --git a/debian/tests/1065022-futureproofing b/debian/tests/1065022-futureproofing
index d84a423365..d1dec80ef4 100755
--- a/debian/tests/1065022-futureproofing
+++ b/debian/tests/1065022-futureproofing
@@ -17,13 +17,16 @@ srcdir="$(pwd)"
 tmpdir="$(mktemp -d)"
 cd "$tmpdir"
 
+# Machine-readable TAP on fd 3, human-readable diagnostics on fds 1 and 2
+exec 3>&1 >&2
+
 assert () {
     n=$(( n + 1 ))
 
     if "$@"; then
-        echo "ok $n - $*"
+        echo "ok $n - $*" >&3
     else
-        echo "not ok $n - $* exit status $?"
+        echo "not ok $n - $* exit status $?" >&3
         failed=1
     fi
 }
@@ -32,9 +35,9 @@ assert_not () {
     n=$(( n + 1 ))
 
     if ! "$@"; then
-        echo "ok $n - unsuccessful as expected: $*"
+        echo "ok $n - unsuccessful as expected: $*" >&3
     else
-        echo "not ok $n - should not have succeeded: $*"
+        echo "not ok $n - should not have succeeded: $*" >&3
         failed=1
     fi
 }
@@ -56,6 +59,10 @@ fi
 # This assumes that libglib2.0-0t64 has at least one each of Breaks, Provides
 # and Replaces, and will need to be adjusted if that assumption is broken in
 # the future for whatever reason.
+dpkg-query -s "$binary_package"
+# The $ substitution is to be expanded by dpkg-query:
+# shellcheck disable=SC2016
+binary_version="$(dpkg-query -W -f '${Version}' "$binary_package")"
 dpkg-repack --generate "$binary_package"
 grep -q '^Breaks:' dpkg-repack.*/DEBIAN/control
 grep -q '^Provides:' dpkg-repack.*/DEBIAN/control
@@ -65,15 +72,18 @@ grep -q '^Replaces:' dpkg-repack.*/DEBIAN/control
 # shellcheck disable=SC2016
 env \
     binary_package="$binary_package" \
+    binary_version="$binary_version" \
     future_binary_package="$future_binary_package" \
     perl -p -i \
         -e 's/^Package:.*$/Package: $ENV{future_binary_package}/;' \
         -e 's/^(Breaks:.*)$/$1, $ENV{binary_package}/;' \
-        -e 's/^(Provides:.*)$/$1, $ENV{binary_package}/;' \
+        -e 's/^(Provides:.*)$/$1, $ENV{binary_package} (= $ENV{binary_version})/;' \
         -e 's/^(Replaces:.*)$/$1, $ENV{binary_package}/;' \
         dpkg-repack.*/DEBIAN/control
 dpkg-deb --build dpkg-repack.* "$future_binary_package.deb"
-apt-get -y install ./"$future_binary_package.deb"
+dpkg-deb --info "$future_binary_package.deb"
+dpkg-deb --contents "$future_binary_package.deb"
+apt-get -y install ./"$future_binary_package.deb" dconf-gsettings-backend gsettings-desktop-schemas
 
 assert test -e /usr/share/glib-2.0/schemas/org.gnome.desktop.interface.gschema.xml
 assert test -s /usr/share/glib-2.0/schemas/gschemas.compiled
@@ -120,7 +130,7 @@ for f in /usr/lib/*/gio/modules/giomodule.cache; do
     assert_not test -e "$f"
 done
 
-echo "1..$n"
+echo "1..$n" >&3
 exit "$failed"
 
 # vim:set sw=4 sts=4 et:
diff --git a/debian/tests/manual/1065022.sh b/debian/tests/manual/1065022.sh
index 6330eb751d..6aaf7ec201 100755
--- a/debian/tests/manual/1065022.sh
+++ b/debian/tests/manual/1065022.sh
@@ -1,5 +1,5 @@
 #!/bin/sh
-# Copyright 2024 Simon McVittie
+# Copyright 2024-2025 Simon McVittie
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 # Reproducer for <https://bugs.debian.org/1065022>.
@@ -8,6 +8,19 @@
 # libglib2.0-0, for example:
 # podman run --rm -it -v $(pwd):$(pwd):ro -w $(pwd) debian:bookworm-slim debian/tests/manual/1065022.sh
 # podman run --rm -it -v $(pwd):$(pwd):ro -w $(pwd) debian:sid-20240110-slim debian/tests/manual/1065022.sh
+#
+# To test proposed packages for bookworm and/or trixie, generate a
+# Packages file in the directory with the packages
+# (dpkg-scanpackages --multiversion . > Packages)
+# and add
+# -v /proposed-bookworm-debs-here:/mnt/bookworm:ro
+# -v /proposed-trixie-debs-here:/mnt/trixie:ro
+# to the podman command-line.
+#
+# Optional argument:
+# - 1110696 to reproduce <https://bugs.debian.org/1110696>
+# - extra-schema or extra-module to exercise additional safety check added
+#   while fixing <https://bugs.debian.org/1110696>
 
 set -eux
 
@@ -29,6 +42,12 @@ assert () {
     fi
 }
 
+# Add a deb822-formatted apt source at this location if you are testing a
+# locally-built glib2.0 for bookworm before upload
+if [ -e /mnt/bookworm/Packages ]; then
+    echo "deb [trusted=yes] file:///mnt/bookworm ./" > /etc/apt/sources.list.d/proposed.list
+fi
+
 # Preconditions: install libglib2.0-0, libglib2.0-0t64, at least one
 # GSettings schema and at least one GIO module.
 dpkg --add-architecture "$other_arch"
@@ -51,29 +70,39 @@ for tuple in "$this_tuple" "$other_tuple"; do
     test -s "$f"
 done
 
+# Make it visible what the postrm is doing
+sed -i -e 's/^set -e$/&x/g' /var/lib/dpkg/info/libglib2.0-0*.postrm || true
+
 # Remove but do not purge the other architecture's packages
 apt-get -y remove "libglib2.0-0:$other_arch" "dconf-gsettings-backend:$other_arch"
 apt-get -y autoremove
 
-# Upgrade to current unstable, with libglib2.0-0t64
+if [ "${1-}" = 1110696 ]; then
+    # To reproduce #1110696, completely remove the other architecture
+    apt-get -y remove --allow-remove-essential $(dpkg-query -W -f '${binary:Package}\n' | grep :i386)
+    dpkg --remove-architecture i386
+fi
+
+# Upgrade to trixie with libglib2.0-0t64
 cat > /etc/apt/sources.list.d/debian.sources <<EOF
 Types: deb
 URIs: http://deb.debian.org/debian
-Suites: sid
+Suites: trixie
 Components: main
 Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
 EOF
 
 # Add a deb822-formatted apt source at this location if you are testing a
 # locally-built glib2.0 before upload
-if [ -e "debian/tests/manual/local-1065022.sources" ]; then
-    install -m644 "debian/tests/manual/local-1065022.sources" /etc/apt/sources.list.d/
+if [ -e /mnt/trixie/Packages ]; then
+    echo "deb [trusted=yes] file:///mnt/trixie ./" > /etc/apt/sources.list.d/proposed.list
 fi
 
 # Reproducer (1): Upgrade to libglib2.0-0t64. This runs the postrm from
 # libglib2.0-0, which deletes necessary files.
 apt-get -y update
 apt-get -y install --purge libglib2.0-0t64
+sed -i -e 's/^set -e$/&x/g' /var/lib/dpkg/info/libglib2.0-0*.postrm || true
 
 assert test -e /usr/share/glib-2.0/schemas/org.gnome.desktop.interface.gschema.xml
 assert test -s /usr/share/glib-2.0/schemas/gschemas.compiled
@@ -87,6 +116,7 @@ assert test -s "/usr/lib/$this_tuple/gio/modules/giomodule.cache"
 # Workaround: Trigger the postinst of libglib2.0-0t64, which will regenerate
 # the generated files.
 apt-get -y install --reinstall libglib2.0-0t64
+sed -i -e 's/^set -e$/&x/g' /var/lib/dpkg/info/libglib2.0-0*.postrm || true
 
 assert test -e /usr/share/glib-2.0/schemas/org.gnome.desktop.interface.gschema.xml
 assert test -s /usr/share/glib-2.0/schemas/gschemas.compiled
@@ -99,9 +129,11 @@ assert test -s "/usr/lib/$this_tuple/gio/modules/giomodule.cache"
 
 # Reproducer (2): Purge the other multiarch instance of libglib2.0-0.
 # Again this runs the postrm from libglib2.0-0, which deletes necessary files.
+# (This is also the relevant part for reproducing #1110696.)
 dpkg --purge "libglib2.0-0:$other_arch"
 
 assert test -e /usr/share/glib-2.0/schemas/org.gnome.desktop.interface.gschema.xml
+# This is the assertion that will fail for #1110696
 assert test -s /usr/share/glib-2.0/schemas/gschemas.compiled
 
 assert test -e "/usr/lib/$this_tuple/gio/modules/libdconfsettings.so"
@@ -110,6 +142,47 @@ assert test -s "/usr/lib/$this_tuple/gio/modules/libdconfsettings.so"
 assert test -e "/usr/lib/$this_tuple/gio/modules/giomodule.cache"
 assert test -s "/usr/lib/$this_tuple/gio/modules/giomodule.cache"
 
+case "${1-}" in
+    (extra-schema)
+        touch "/usr/share/glib-2.0/schemas/UNPACKAGED.xml"
+        ;;
+    (extra-module)
+        touch "/usr/lib/$this_tuple/gio/modules/UNPACKAGED.so"
+        ;;
+esac
+
+# Merely removing GLib does not delete the generated files, although
+# they might have become empty.
+apt-get -y remove libglib2.0-0t64
+assert test -e /usr/share/glib-2.0/schemas/gschemas.compiled
+assert test -e "/usr/lib/$this_tuple/gio/modules/giomodule.cache"
+
+# Purge GLib completely, taking dependent packages with it.
+apt-get -y remove --purge libglib2.0-0t64
+
+case "${1-}" in
+    (extra-schema)
+        # Because /usr/share/glib-2.0/schemas/UNPACKAGED.xml exists,
+        # we err on the side of caution and do not remove the compiled
+        # schemas.
+        assert test -e /usr/share/glib-2.0/schemas/gschemas.compiled
+        ;;
+    (*)
+        # Otherwise, we should remove it during purge.
+        assert test ! -e /usr/share/glib-2.0/schemas/gschemas.compiled
+        ;;
+esac
+
+# As above, but for GIO modules.
+case "${1-}" in
+    (extra-module)
+        assert test -e "/usr/lib/$this_tuple/gio/modules/giomodule.cache"
+        ;;
+    (*)
+        assert test ! -e "/usr/lib/$this_tuple/gio/modules/giomodule.cache"
+        ;;
+esac
+
 echo "1..$n"
 exit "$failed"
 
diff --git a/gio/gfilenamecompleter.c b/gio/gfilenamecompleter.c
index 295ade05b2..795418cbc6 100644
--- a/gio/gfilenamecompleter.c
+++ b/gio/gfilenamecompleter.c
@@ -342,11 +342,13 @@ init_completion (GFilenameCompleter *completer,
 		 char **basename_out)
 {
   gboolean should_escape;
-  GFile *file, *parent;
+  GFile *file = NULL, *parent = NULL;
   char *basename;
   char *t;
   size_t len;
+  GList *basenames;
 
+  basenames = NULL;
   *basename_out = NULL;
   
   should_escape = ! (g_path_is_absolute (initial_text) || *initial_text == '~');
@@ -355,23 +357,20 @@ init_completion (GFilenameCompleter *completer,
   
   if (len > 0 &&
       initial_text[len - 1] == '/')
-    return NULL;
+    goto out;
   
   file = g_file_parse_name (initial_text);
   parent = g_file_get_parent (file);
   if (parent == NULL)
-    {
-      g_object_unref (file);
-      return NULL;
-    }
+    goto out;
 
   if (completer->basenames_dir == NULL ||
       completer->basenames_are_escaped != should_escape ||
       !g_file_equal (parent, completer->basenames_dir))
     {
       schedule_load_basenames (completer, parent, should_escape);
-      g_object_unref (file);
-      return NULL;
+
+      goto out;
     }
   
   basename = g_file_get_basename (file);
@@ -388,12 +387,17 @@ init_completion (GFilenameCompleter *completer,
       g_free (t);
       
       if (basename == NULL)
-	return NULL;
+        goto out;
     }
 
+  basenames = completer->basenames;
   *basename_out = basename;
 
-  return completer->basenames;
+out:
+  g_clear_object (&file);
+  g_clear_object (&parent);
+
+  return basenames;
 }
 
 /**
diff --git a/gio/glocalfile.c b/gio/glocalfile.c
index d9903b4e47..1e5c301542 100644
--- a/gio/glocalfile.c
+++ b/gio/glocalfile.c
@@ -1189,6 +1189,7 @@ g_local_file_set_display_name (GFile         *file,
       if (errsv != ENOENT)
         {
           g_set_io_error (error, _("Error renaming file %s: %s"), new_file, errsv);
+          g_object_unref (new_file);
           return NULL;
         }
     }
@@ -1196,6 +1197,7 @@ g_local_file_set_display_name (GFile         *file,
     {
       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_EXISTS,
                            _("Can’t rename file, filename already exists"));
+      g_object_unref (new_file);
       return NULL;
     }
 
diff --git a/gio/gsettings.c b/gio/gsettings.c
index fbee36b3a3..628f8b572d 100644
--- a/gio/gsettings.c
+++ b/gio/gsettings.c
@@ -3161,6 +3161,14 @@ bind_with_mapping_invoke_get (GValue *value,
   g_closure_invoke (data->get_mapping_closure, &out, 2, params, /* hint = */ NULL);
 
   retval = g_value_get_boolean (&out);
+  if (retval)
+    {
+      const GValue *out_value = g_value_get_boxed (&params[0]);
+
+      g_assert (out_value != NULL);
+
+      g_value_copy (out_value, value);
+    }
 
   g_value_unset (&out);
   g_value_unset (&params[0]);
diff --git a/gio/tests/gsettings.c b/gio/tests/gsettings.c
index 60f2aebae8..69e92c051f 100644
--- a/gio/tests/gsettings.c
+++ b/gio/tests/gsettings.c
@@ -1827,6 +1827,7 @@ test_bind_with_mapping_closures_parameters (void)
   GSettings *settings;
   GClosure *get;
   GClosure *set;
+  gboolean val;
   BindWithMappingData data = { FALSE, FALSE, FALSE, FALSE };
 
   settings = g_settings_new ("org.gtk.test.binding");
@@ -1843,6 +1844,8 @@ test_bind_with_mapping_closures_parameters (void)
 
   g_assert_true (data.get_called);
   g_assert_false (data.set_called);
+  g_object_get (obj, "bool", &val, NULL);
+  g_assert_true (val);
 
   data.get_called = FALSE;
   g_object_set (obj, "bool", FALSE, NULL);
diff --git a/glib/gfileutils.c b/glib/gfileutils.c
index bc4bcf1f4d..9930030d25 100644
--- a/glib/gfileutils.c
+++ b/glib/gfileutils.c
@@ -1517,9 +1517,9 @@ get_tmp_file (gchar            *tmpl,
   static const char letters[] =
     "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
   static const int NLETTERS = sizeof (letters) - 1;
-  gint64 value;
-  gint64 now_us;
-  static int counter = 0;
+  guint64 value;
+  guint64 now_us;
+  static guint counter = 0;
 
   g_return_val_if_fail (tmpl != NULL, -1);
 
@@ -1538,7 +1538,7 @@ get_tmp_file (gchar            *tmpl,
 
   for (count = 0; count < 100; value += 7777, ++count)
     {
-      gint64 v = value;
+      guint64 v = value;
 
       /* Fill in the random bits.  */
       XXXXXX[0] = letters[v % NLETTERS];
diff --git a/glib/gthreadpool.c b/glib/gthreadpool.c
index 10fa2bceb3..e511102c38 100644
--- a/glib/gthreadpool.c
+++ b/glib/gthreadpool.c
@@ -582,6 +582,7 @@ g_thread_pool_new_full (GFunc           func,
 {
   GRealThreadPool *retval;
   G_LOCK_DEFINE_STATIC (init);
+  GError *local_error = NULL;
 
   g_return_val_if_fail (func, NULL);
   g_return_val_if_fail (!exclusive || max_threads != -1, NULL);
@@ -629,22 +630,19 @@ g_thread_pool_new_full (GFunc           func,
 
       spawn_thread_queue = g_async_queue_new ();
       g_cond_init (&spawn_thread_cond);
-      pool_spawner = g_thread_new ("pool-spawner", g_thread_pool_spawn_thread, NULL);
+      pool_spawner = g_thread_try_new ("pool-spawner", g_thread_pool_spawn_thread, NULL, &local_error);
       g_ignore_leak (pool_spawner);
     }
   G_UNLOCK (init);
 
-  if (retval->pool.exclusive)
+  if (retval->pool.exclusive && local_error == NULL)
     {
       g_async_queue_lock (retval->queue);
 
       while (retval->num_threads < (guint) retval->max_threads)
         {
-          GError *local_error = NULL;
-
           if (!g_thread_pool_start_thread (retval, &local_error))
             {
-              g_propagate_error (error, local_error);
               break;
             }
         }
@@ -652,6 +650,18 @@ g_thread_pool_new_full (GFunc           func,
       g_async_queue_unlock (retval->queue);
     }
 
+  if (local_error != NULL)
+    {
+      /* Failed to create pool spawner or failed to start a thread,
+       * so we must return NULL */
+      g_propagate_error (error, local_error);
+
+      g_clear_pointer (&retval->queue, g_async_queue_unref);
+      g_cond_clear (&retval->cond);
+
+      g_clear_pointer (&retval, g_free);
+    }
+
   return (GThreadPool*) retval;
 }
 
diff --git a/meson.build b/meson.build
index 2aff65bc02..8f3f686add 100644
--- a/meson.build
+++ b/meson.build
@@ -1,5 +1,5 @@
 project('glib', 'c',
-  version : '2.84.3',
+  version : '2.84.4',
   # NOTE: See the policy in docs/meson-version.md before changing the Meson dependency
   meson_version : '>= 1.4.0',
   default_options : [
