diff --git a/Revert-Fix-pthread-id-stored-in-GC_threads-of-child-process.patch b/Revert-Fix-pthread-id-stored-in-GC_threads-of-child-process.patch new file mode 100644 index 0000000000000000000000000000000000000000..34b43e8d00ad2f7e71a5c3cc52defb8ae5dc288d --- /dev/null +++ b/Revert-Fix-pthread-id-stored-in-GC_threads-of-child-process.patch @@ -0,0 +1,177 @@ +From 74fc05d128c4ad9860740d73b4c7fd43ea18e74a Mon Sep 17 00:00:00 2001 +From: Ivan Maidanski +Date: Thu, 12 Dec 2024 08:13:42 +0300 +Subject: [PATCH] Fix pthread id stored in GC_threads of child process (a + cherry-pick of commit bee3ff9c4 from 'master') + +Issue #682 (bdwgc). + +`GC_remove_all_threads_but_me()` should also update thread identifiers +stored in the table for the current thread. + +* pthread_support.c [CAN_HANDLE_FORK] (GC_parent_pthread_self): New +static variable. +* pthread_support.c [CAN_HANDLE_FORK] (GC_remove_all_threads_but_me): +Update comment; remove `self` local variable and use +`GC_parent_pthread_self` instead; move `me` local variable out of +loops; call `store_to_threads_table(hv,NULL)` instead of +`store_to_threads_table(hv,me)` inside loop; check `me` is not null +after loop; update `me->id` and call +`store_to_threads_table(THREAD_TABLE_INDEX(me->id),me)`. +* pthread_support.c [CAN_HANDLE_FORK && GC_DARWIN_THREADS] +(GC_remove_all_threads_but_me): Move setting +`me->stop_info.mach_thread` out of loops. +* pthread_support.c [CAN_HANDLE_FORK && USE_TKILL_ON_ANDROID] +(GC_remove_all_threads_but_me): Move setting `me->kernel_id` out of +loops. +* pthread_support.c [CAN_HANDLE_FORK && THREAD_LOCAL_ALLOC +&& !USE_CUSTOM_SPECIFIC] (GC_remove_all_threads_but_me): Move call +`GC_setspecific(GC_thread_key,&me->tlfs)` out of loops. +* pthread_support.c [CAN_HANDLE_FORK] (fork_prepare_proc): Set +`GC_parent_pthread_self`. +* pthread_support.c [CAN_HANDLE_FORK && GC_ASSERTIONS] +(fork_parent_proc, fork_child_proc): Clear `GC_parent_pthread_self` at +the end of function. +--- + pthread_support.c | 84 +++++++++++++++++------------------------------ + 1 file changed, 30 insertions(+), 54 deletions(-) + +diff --git a/pthread_support.c b/pthread_support.c +index 3a4b22b..3d85bc5 100644 +--- a/pthread_support.c ++++ b/pthread_support.c +@@ -829,28 +829,47 @@ GC_API void GC_CALL GC_register_altstack(void *stack, GC_word stack_size, + GC_threads[hv] = me; + } + +-/* Value of pthread_self() of the thread which called fork(). */ +-STATIC pthread_t GC_parent_pthread_self; +- +-/* Remove all entries from the GC_threads table, except the one for */ +-/* the current thread. Also update thread identifiers stored in */ +-/* the table for the current thread. We need to do this in the */ +-/* child process after a fork(), since only the current thread */ +-/* survives in the child. */ ++/* Remove all entries from the GC_threads table, except the */ ++/* one for the current thread. We need to do this in the child */ ++/* process after a fork(), since only the current thread */ ++/* survives in the child. */ + STATIC void GC_remove_all_threads_but_me(void) + { ++ pthread_t self = pthread_self(); + int hv; +- GC_thread me = NULL; + + for (hv = 0; hv < THREAD_TABLE_SZ; ++hv) { + GC_thread p, next; ++ GC_thread me = NULL; + + for (p = GC_threads[hv]; 0 != p; p = next) { + next = p -> next; +- if (THREAD_EQUAL(p -> id, GC_parent_pthread_self) ++ if (THREAD_EQUAL(p -> id, self) + && me == NULL) { /* ignore dead threads with the same id */ + me = p; + p -> next = 0; ++# ifdef GC_DARWIN_THREADS ++ /* Update thread Id after fork (it is OK to call */ ++ /* GC_destroy_thread_local and GC_free_inner */ ++ /* before update). */ ++ me -> stop_info.mach_thread = mach_thread_self(); ++# endif ++# ifdef USE_TKILL_ON_ANDROID ++ me -> kernel_id = gettid(); ++# endif ++# if defined(THREAD_LOCAL_ALLOC) && !defined(USE_CUSTOM_SPECIFIC) ++ { ++ int res; ++ ++ /* Some TLS implementations might be not fork-friendly, so */ ++ /* we re-assign thread-local pointer to 'tlfs' for safety */ ++ /* instead of the assertion check (again, it is OK to call */ ++ /* GC_destroy_thread_local and GC_free_inner before). */ ++ res = GC_setspecific(GC_thread_key, &me->tlfs); ++ if (COVERT_DATAFLOW(res) != 0) ++ ABORT("GC_setspecific failed (in child)"); ++ } ++# endif + } else { + # ifdef THREAD_LOCAL_ALLOC + if (!(p -> flags & FINISHED)) { +@@ -870,44 +889,8 @@ STATIC void GC_remove_all_threads_but_me(void) + # endif + } + } +- store_to_threads_table(hv, NULL); +- } +- +-# if defined(CPPCHECK) || defined(LINT2) +- if (NULL == me) +- ABORT("Current thread is not found after fork"); +-# else +- GC_ASSERT(me != NULL); +-# endif +- /* Update pthread's id as it is not guaranteed to be the same */ +- /* between this (child) process and the parent one. */ +- me -> id = pthread_self(); +-# ifdef GC_DARWIN_THREADS +- /* Update thread Id after fork (it is OK to call */ +- /* GC_destroy_thread_local and GC_free_inner */ +- /* before update). */ +- me -> stop_info.mach_thread = mach_thread_self(); +-# endif +-# ifdef USE_TKILL_ON_ANDROID +- me -> kernel_id = gettid(); +-# endif +- +- /* Put "me" back to GC_threads. */ +- store_to_threads_table(THREAD_TABLE_INDEX(me -> id), me); +- +-# if defined(THREAD_LOCAL_ALLOC) && !defined(USE_CUSTOM_SPECIFIC) +- { +- int res; +- +- /* Some TLS implementations might be not fork-friendly, so */ +- /* we re-assign thread-local pointer to 'tlfs' for safety */ +- /* instead of the assertion check (again, it is OK to call */ +- /* GC_destroy_thread_local and GC_free_inner before). */ +- res = GC_setspecific(GC_thread_key, &me->tlfs); +- if (COVERT_DATAFLOW(res) != 0) +- ABORT("GC_setspecific failed (in child)"); ++ store_to_threads_table(hv, me); + } +-# endif + } + #endif /* CAN_HANDLE_FORK */ + +@@ -1214,7 +1197,6 @@ static void fork_prepare_proc(void) + /* the (one remaining thread in) the child. */ + LOCK(); + DISABLE_CANCEL(fork_cancel_state); +- GC_parent_pthread_self = pthread_self(); + /* Following waits may include cancellation points. */ + # if defined(PARALLEL_MARK) + if (GC_parallel) +@@ -1255,9 +1237,6 @@ static void fork_parent_proc(void) + } + # endif + RESTORE_CANCEL(fork_cancel_state); +-# ifdef GC_ASSERTIONS +- BZERO(&GC_parent_pthread_self, sizeof(pthread_t)); +-# endif + UNLOCK(); + } + +@@ -1305,9 +1284,6 @@ static void fork_child_proc(void) + /* Clean up the thread table, so that just our thread is left. */ + GC_remove_all_threads_but_me(); + RESTORE_CANCEL(fork_cancel_state); +-# ifdef GC_ASSERTIONS +- BZERO(&GC_parent_pthread_self, sizeof(pthread_t)); +-# endif + UNLOCK(); + /* Even though after a fork the child only inherits the single */ + /* thread that called the fork(), if another thread in the parent */ +-- +2.47.3 + diff --git a/Revert-Fix-pthread-id-stored-in-key-thread_specific_data-of-child.patch b/Revert-Fix-pthread-id-stored-in-key-thread_specific_data-of-child.patch new file mode 100644 index 0000000000000000000000000000000000000000..59826924e691c453f8e248998d5b280a65151d66 --- /dev/null +++ b/Revert-Fix-pthread-id-stored-in-key-thread_specific_data-of-child.patch @@ -0,0 +1,173 @@ +From 2cd0f5e56718a053341d1b5e7df7a3cab9a5ceaa Mon Sep 17 00:00:00 2001 +From: Ivan Maidanski +Date: Fri, 13 Dec 2024 00:26:38 +0300 +Subject: [PATCH] Fix pthread id stored in key thread_specific_data of child + process (a cherry-pick of commit fa63cef86 from 'master') + +Issue #682 (bdwgc). + +Update thread-specific data for the survived thread of the child +process. This is needed because `pthread_self()` value is not +guaranteed to be the same between the child and parent processes. +Matters only if `USE_CUSTOM_SPECIFIC` macro is defined. + +* include/private/gc_priv.h [CAN_HANDLE_FORK && GC_PTHREADS]: Include +`pthread.h`. +* include/private/gc_priv.h [CAN_HANDLE_FORK && GC_PTHREADS] +(GC_arrays._parent_pthread_self): New field; add comment. +* include/private/gc_priv.h [CAN_HANDLE_FORK && GC_PTHREADS] +(GC_parent_pthread_self): Define as a macro. +* include/private/specific.h [CAN_HANDLE_FORK] +(GC_update_specific_after_fork): Declare function. +* pthread_support.c [CAN_HANDLE_FORK] (GC_parent_pthread_self): Remove +static variable. +* pthread_support.c [CAN_HANDLE_FORK && THREAD_LOCAL_ALLOC +&& USE_CUSTOM_SPECIFIC] (GC_remove_all_threads_but_me): Call +`GC_update_specific_after_fork()` (after `store_to_threads_table()` +call). +* specific.c [USE_CUSTOM_SPECIFIC && CAN_HANDLE_FORK] +(GC_update_specific_after_fork): Implement. +--- + include/private/gc_priv.h | 11 ----------- + include/private/specific.h | 7 ------- + pthread_support.c | 31 +++++++++++++++---------------- + specific.c | 27 --------------------------- + 4 files changed, 15 insertions(+), 61 deletions(-) + +diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h +index 21cd282..798e5f8 100644 +--- a/include/private/gc_priv.h ++++ b/include/private/gc_priv.h +@@ -832,10 +832,6 @@ EXTERN_C_END + + #include + +-#if defined(CAN_HANDLE_FORK) && defined(GC_PTHREADS) +-# include /* for pthread_t */ +-#endif +- + #if __STDC_VERSION__ >= 201112L + # include /* for static_assert */ + #endif +@@ -1556,13 +1552,6 @@ struct _GC_arrays { + # endif + size_t _ed_size; /* Current size of above arrays. */ + size_t _avail_descr; /* Next available slot. */ +- +-# if defined(CAN_HANDLE_FORK) && defined(GC_PTHREADS) +- /* Value of pthread_self() of the thread which called fork(). */ +-# define GC_parent_pthread_self GC_arrays._parent_pthread_self +- pthread_t _parent_pthread_self; +-# endif +- + typed_ext_descr_t *_ext_descriptors; /* Points to array of extended */ + /* descriptors. */ + GC_mark_proc _mark_procs[MAX_MARK_PROCS]; +diff --git a/include/private/specific.h b/include/private/specific.h +index 029fc7f..3ed7564 100644 +--- a/include/private/specific.h ++++ b/include/private/specific.h +@@ -109,13 +109,6 @@ GC_INNER int GC_setspecific(tsd * key, void * value); + GC_remove_specific_after_fork(key, pthread_self()) + GC_INNER void GC_remove_specific_after_fork(tsd * key, pthread_t t); + +-#ifdef CAN_HANDLE_FORK +- /* Update thread-specific data for the survived thread of the child */ +- /* process. Should be called once after removing thread-specific data */ +- /* for other threads. */ +- GC_INNER void GC_update_specific_after_fork(tsd *key); +-#endif +- + /* An internal version of getspecific that assumes a cache miss. */ + GC_INNER void * GC_slow_getspecific(tsd * key, word qtid, + tse * volatile * cache_entry); +diff --git a/pthread_support.c b/pthread_support.c +index 937846c..3a4b22b 100644 +--- a/pthread_support.c ++++ b/pthread_support.c +@@ -829,6 +829,9 @@ GC_API void GC_CALL GC_register_altstack(void *stack, GC_word stack_size, + GC_threads[hv] = me; + } + ++/* Value of pthread_self() of the thread which called fork(). */ ++STATIC pthread_t GC_parent_pthread_self; ++ + /* Remove all entries from the GC_threads table, except the one for */ + /* the current thread. Also update thread identifiers stored in */ + /* the table for the current thread. We need to do this in the */ +@@ -892,22 +895,18 @@ STATIC void GC_remove_all_threads_but_me(void) + /* Put "me" back to GC_threads. */ + store_to_threads_table(THREAD_TABLE_INDEX(me -> id), me); + +-# ifdef THREAD_LOCAL_ALLOC +-# ifdef USE_CUSTOM_SPECIFIC +- GC_update_specific_after_fork(GC_thread_key); +-# else +- { +- int res; +- +- /* Some TLS implementations might be not fork-friendly, so */ +- /* we re-assign thread-local pointer to 'tlfs' for safety */ +- /* instead of the assertion check (again, it is OK to call */ +- /* GC_destroy_thread_local and GC_free_inner before). */ +- res = GC_setspecific(GC_thread_key, &me->tlfs); +- if (COVERT_DATAFLOW(res) != 0) +- ABORT("GC_setspecific failed (in child)"); +- } +-# endif ++# if defined(THREAD_LOCAL_ALLOC) && !defined(USE_CUSTOM_SPECIFIC) ++ { ++ int res; ++ ++ /* Some TLS implementations might be not fork-friendly, so */ ++ /* we re-assign thread-local pointer to 'tlfs' for safety */ ++ /* instead of the assertion check (again, it is OK to call */ ++ /* GC_destroy_thread_local and GC_free_inner before). */ ++ res = GC_setspecific(GC_thread_key, &me->tlfs); ++ if (COVERT_DATAFLOW(res) != 0) ++ ABORT("GC_setspecific failed (in child)"); ++ } + # endif + } + #endif /* CAN_HANDLE_FORK */ +diff --git a/specific.c b/specific.c +index 1293d40..09387ac 100644 +--- a/specific.c ++++ b/specific.c +@@ -133,33 +133,6 @@ GC_INNER void GC_remove_specific_after_fork(tsd * key, pthread_t t) + ABORT("pthread_mutex_unlock failed (remove_specific after fork)"); + } + +-#ifdef CAN_HANDLE_FORK +- GC_INNER void +- GC_update_specific_after_fork(tsd *key) +- { +- unsigned hash_val = HASH(GC_parent_pthread_self); +- tse *entry; +- +- GC_ASSERT(I_HOLD_LOCK()); +-# ifdef LINT2 +- pthread_mutex_lock(&key->lock); +-# endif +- entry = key->hash[hash_val].p; +- if (EXPECT(entry != NULL, TRUE)) { +- GC_ASSERT(THREAD_EQUAL(entry->thread, GC_parent_pthread_self)); +- GC_ASSERT(NULL == entry->next); +- /* Remove the entry from the table. */ +- key->hash[hash_val].p = NULL; +- entry->thread = pthread_self(); +- /* Then put the entry back to the table (based on new hash value). */ +- key->hash[HASH(entry->thread)].p = entry; +- } +-# ifdef LINT2 +- (void)pthread_mutex_unlock(&key->lock); +-# endif +- } +-#endif +- + /* Note that even the slow path doesn't lock. */ + GC_INNER void * GC_slow_getspecific(tsd * key, word qtid, + tse * volatile * cache_ptr) +-- +2.47.3 + diff --git a/gc.spec b/gc.spec index 9af5091ebe2de7e7ab8f9a8b999743163f8e529e..0c53050225836f2849285002e5f7b6bd75235663 100644 --- a/gc.spec +++ b/gc.spec @@ -1,6 +1,6 @@ Name: gc Version: 8.2.10 -Release: 1 +Release: 2 Summary: A garbage collector for C and C++ License: BSD-3-Clause Url: http://www.hboehm.info/gc/ @@ -9,6 +9,11 @@ Patch1: gc-8.2.10-sw.patch Patch2: 0001-add-loongarch-architecture.patch Patch3: gc-8.2.6-make-atomic_ops_private.patch +# https://gitlab.archlinux.org/archlinux/packaging/packages/gc/-/issues/2 +# https://github.com/bdwgc/bdwgc/issues/783 +Patch6999: Revert-Fix-pthread-id-stored-in-key-thread_specific_data-of-child.patch +Patch6998: Revert-Fix-pthread-id-stored-in-GC_threads-of-child-process.patch + BuildRequires: gcc-c++ BuildRequires: autoconf automake libtool BuildRequires: pkgconfig(atomic_ops) @@ -27,7 +32,6 @@ Requires: %{name}%{?_isa} = %{version}-%{release} %prep %autosetup -n %{name}-%{version} -p1 - %build # refresh auto*/libtool to purge rpaths rm -f libtool libtool.m4 @@ -79,6 +83,9 @@ rm -rfv %{buildroot}%{_datadir}/gc/ %{_mandir}/man3/gc.3* %changelog +* Thu Oct 23 2025 Funda Wang - 8.2.10-2 +- revert two commits which cause core dumps in some gtk-applications + * Sun Oct 19 2025 Funda Wang - 8.2.10-1 - update to 8.2.10