summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorIvan Maidanski <ivmai@mail.ru>2022-03-16 06:54:03 +0300
committerIvan Maidanski <ivmai@mail.ru>2022-03-16 11:07:15 +0300
commit673f0cf3f25ad914bd273d50d9973f9dc92ff801 (patch)
tree48c14975710b24adef8e8267e0fbdea957d4e8e0 /tests
parent4f57974b53c3acab0cfca1ee655a75026ccd5f7e (diff)
downloadbdwgc-673f0cf3f25ad914bd273d50d9973f9dc92ff801.tar.gz
Fix SIGSEGV caused by dropped stack access from child process in gctest
(fix of commit c808151a0) Issue #256 (bdwgc). Previously, a local variable was passed in gctest to GC_move_disappearing_link as a link to clear, this led to a memory access violation during garbage collection in the child process if the fork occurred between GC_move_disappearing_link(..., &new_link) and GC_unregister_disappearing_link(&new_link). This commit changes the mentioned local variable (new_link) use - now it contains a pointer to a heap-allocated link rather then containing just a link. * tests/gctest.c (mktree): Change type of new_link from void* to void**; initialize it to GC_NEW(void*) and ensure it is non-null; replace new_link with *new_link; add comment new_link object is reclaimed correctly even if the thread is dropped in the child process between GC_move_disappearing_link(new_link) and GC_unregister_disappearing_link.
Diffstat (limited to 'tests')
-rw-r--r--tests/gctest.c24
1 files changed, 15 insertions, 9 deletions
diff --git a/tests/gctest.c b/tests/gctest.c
index 86692503..97081afa 100644
--- a/tests/gctest.c
+++ b/tests/gctest.c
@@ -932,9 +932,10 @@ tn * mktree(int n)
if (AO_fetch_and_add1(&extra_count) % 119 == 0) {
# ifndef GC_NO_FINALIZATION
int my_index;
- void *new_link;
+ void **new_link = GC_NEW(void *);
# endif
+ CHECK_OUT_OF_MEMORY(new_link);
{
FINALIZER_LOCK();
/* Losing a count here causes erroneous report of failure. */
@@ -964,18 +965,23 @@ tn * mktree(int n)
GC_printf("GC_move_disappearing_link(link,link) failed\n");
FAIL;
}
- new_link = (void *)live_indicators[my_index];
+ *new_link = (void *)live_indicators[my_index];
if (GC_move_disappearing_link((void **)(&(live_indicators[my_index])),
- &new_link) != GC_SUCCESS) {
+ new_link) != GC_SUCCESS) {
GC_printf("GC_move_disappearing_link(new_link) failed\n");
FAIL;
}
- if (GC_unregister_disappearing_link(&new_link) == 0) {
+ /* Note: if other thread is performing fork at this moment, */
+ /* then the stack of the current thread is dropped (together */
+ /* with new_link variable) in the child process, and */
+ /* GC_dl_hashtbl entry with the link equal to new_link will be */
+ /* removed when a collection occurs (as expected). */
+ if (GC_unregister_disappearing_link(new_link) == 0) {
GC_printf("GC_unregister_disappearing_link failed\n");
FAIL;
}
if (GC_move_disappearing_link((void **)(&(live_indicators[my_index])),
- &new_link) != GC_NOT_FOUND) {
+ new_link) != GC_NOT_FOUND) {
GC_printf("GC_move_disappearing_link(new_link) failed 2\n");
FAIL;
}
@@ -994,18 +1000,18 @@ tn * mktree(int n)
GC_printf("GC_move_long_link(link,link) failed\n");
FAIL;
}
- new_link = live_long_refs[my_index];
+ *new_link = live_long_refs[my_index];
if (GC_move_long_link(&live_long_refs[my_index],
- &new_link) != GC_SUCCESS) {
+ new_link) != GC_SUCCESS) {
GC_printf("GC_move_long_link(new_link) failed\n");
FAIL;
}
- if (GC_unregister_long_link(&new_link) == 0) {
+ if (GC_unregister_long_link(new_link) == 0) {
GC_printf("GC_unregister_long_link failed\n");
FAIL;
}
if (GC_move_long_link(&live_long_refs[my_index],
- &new_link) != GC_NOT_FOUND) {
+ new_link) != GC_NOT_FOUND) {
GC_printf("GC_move_long_link(new_link) failed 2\n");
FAIL;
}