From 8efaa3d291f3f9d035bd8c16995828332f6aeb77 Mon Sep 17 00:00:00 2001 From: hmelder Date: Sat, 15 Mar 2025 12:42:41 +0800 Subject: [PATCH 1/3] Retain and autorelease associated objects properly Apple's objc4 runtime expands the policy bits into the following subcategories: ``` enum { OBJC_ASSOCIATION_SETTER_ASSIGN = 0, OBJC_ASSOCIATION_SETTER_RETAIN = 1, OBJC_ASSOCIATION_SETTER_COPY = 3, OBJC_ASSOCIATION_GETTER_READ = (0 << 8), OBJC_ASSOCIATION_GETTER_RETAIN = (1 << 8), OBJC_ASSOCIATION_GETTER_AUTORELEASE = (2 << 8) }; ``` where OBJC_ASSOCIATION_ASSIGN = 0 OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1 OBJC_ASSOCIATION_COPY_NONATOMIC = 3 OBJC_ASSOCIATION_RETAIN = 01401 OBJC_ASSOCIATION_COPY = 01403 This means that on OBJC_ASSOCIATION_{RETAIN, COPY} and the NONATOMIC counterpart, we need to retain and autorelease the associated object before returning it in objc_getAssociatedObject. --- associate.m | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/associate.m b/associate.m index 79c9713a..2b987f99 100644 --- a/associate.m +++ b/associate.m @@ -341,6 +341,12 @@ id objc_getAssociatedObject(id object, const void *key) struct reference *r = findReference(list, key); if (NULL != r) { + // Check if the policy is OBJC_ASSOCIATION_{RETAIN, COPY} or OBJC_ASSOCIATION_{RETAIN, COPY}_NONATOMIC (LSB set) + // Apple's objc4 retains and autoreleases the object under these policies + if (r->policy & OBJC_ASSOCIATION_RETAIN_NONATOMIC) + { + objc_retainAutorelease(r->object); + } return r->object; } if (class_isMetaClass(object->isa)) @@ -364,6 +370,10 @@ id objc_getAssociatedObject(id object, const void *key) struct reference *r = findReference(list, key); if (NULL != r) { + if (r->policy & OBJC_ASSOCIATION_RETAIN_NONATOMIC) + { + objc_retainAutorelease(r->object); + } return r->object; } } From d19512e095ecedae569200d177e4e6080147a463 Mon Sep 17 00:00:00 2001 From: hmelder Date: Sat, 15 Mar 2025 12:59:58 +0800 Subject: [PATCH 2/3] Test for retained associated object other retain policy --- Test/AssociatedObject.m | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Test/AssociatedObject.m b/Test/AssociatedObject.m index d22044bb..f0266e2a 100644 --- a/Test/AssociatedObject.m +++ b/Test/AssociatedObject.m @@ -41,9 +41,11 @@ int main(void) object = [Associated new]; holder = [Test new]; + size_t rc = object_getRetainCount_np(object); for (uintptr_t i = 1; i <= 20; ++i) { objc_setAssociatedObject(holder, (void*)i, object, OBJC_ASSOCIATION_RETAIN); + assert(rc + i == object_getRetainCount_np(object)); } int lost = 0; for (uintptr_t i = 1; i <= 20; ++i) @@ -53,6 +55,7 @@ int main(void) fprintf(stderr, "lost object %" PRIuPTR "\n", i); ++lost; } + assert(rc + 20 + i == object_getRetainCount_np(object)); } [holder release]; [object release]; From 28ab03adeefbf2897bbda5e13b1371f83bdfafea Mon Sep 17 00:00:00 2001 From: Hugo Melder Date: Sun, 16 Mar 2025 06:27:58 +0100 Subject: [PATCH 3/3] Cirrus: Bump freebsd image versions --- .cirrus.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index 4a43645e..d6985ef3 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -1,11 +1,11 @@ libcxxrt_freebsd_task: matrix: - freebsd_instance: - image_family: freebsd-13-3 + image_family: freebsd-13-5 - freebsd_instance: image_family: freebsd-15-0-snap - freebsd_instance: - image_family: freebsd-14-0 + image_family: freebsd-14-2 install_script: pkg install -y cmake ninja git @@ -31,7 +31,7 @@ libcxxrt_freebsd_task: libcxxrt_master_task: freebsd_instance: - image_family: freebsd-14-0 + image_family: freebsd-14-2 install_script: pkg install -y cmake ninja git clone_script: |