New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Run non-Julia finalizers at exit #19911
Conversation
if (!gc_ptr_tag(v, 1)) { | ||
schedule_finalization(v, f); | ||
} | ||
schedule_finalization(v, f); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is wrong. You have to run the finalizer instead of pushing it to the list.
And the correct fix should be diff --git a/src/gc.c b/src/gc.c
index 83a22e9..4bde4b4 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -246,6 +246,9 @@ static void schedule_all_finalizers(arraylist_t *flist)
if (!gc_ptr_tag(v, 1)) {
schedule_finalization(v, f);
}
+ else {
+ ((void (*)(void*))f)(gc_ptr_clear_tag(v, 1));
+ }
}
flist->len = 0;
} |
@yuyichao That's actually the first thing I tried, but it gave the same segfault in the MPFR test, again at the line that calls the non-Julia finalizer. I'm wondering if that segfault was just hidden because the finalizer didn't get called... |
I didn't do the |
At least your version segfault because it didn't clear the pointer tag and I imagine that's the issue in your other versions too. You didn't see that in you test case because you didn't actually read the pointer. The use of tagged pointers and the restrictions of them in |
Confirmed, this works without segfault on my machine. To be sure, the fact that the |
Line 1603 in 77dfb35
|
Should we add the test case to libccalltest? |
We don't need to add those to |
Thanks for the comments and the explanations. I didn't add the test because I have no idea how to automate it, maybe it's possible to set the exit state in the finalizer or something? |
You can print something |
I have added a test. I used |
|
@@ -798,6 +798,11 @@ let A = [1] | |||
@test ccall((:get_c_int, libccalltest), Cint, ()) == -1 | |||
end | |||
|
|||
# Pointer finalizer at exit (PR #19911) | |||
let result = readstring(`$(Base.julia_cmd()) -e "A = [1]; finalizer(A, cglobal((:c_exit_finalizer, \"$libccalltest\"), Void))"`) | |||
@test result == "c_exit_finalizer" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
4 space indent
@@ -798,6 +798,11 @@ let A = [1] | |||
@test ccall((:get_c_int, libccalltest), Cint, ()) == -1 | |||
end | |||
|
|||
# Pointer finalizer at exit (PR #19911) | |||
let result = readstring(`$(Base.julia_cmd()) -e "A = [1]; finalizer(A, cglobal((:c_exit_finalizer, \"$libccalltest\"), Void))"`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add --startup-file=no
OK, done! |
I did one more update because the pointer tag check failed on 32 bit. |
@@ -973,3 +973,7 @@ JL_DLLEXPORT float32x4_t test_ppc64_vec2(int64_t d1, float32x4_t a, float32x4_t | |||
JL_DLLEXPORT int threadcall_args(int a, int b) { | |||
return a + b; | |||
} | |||
|
|||
JL_DLLEXPORT void c_exit_finalizer(void* v) { | |||
printf("c_exit_finalizer: %d, %u", *(int*)v, (unsigned)((uintptr_t)v & (uintptr_t)1)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be 3
but this is also good enough...
Can we merge this then? |
Since we no longer run finalizers at exit.
It seems function-pointer finalizers are not run at exit. The example at the bottom of this comment illustrates the problem, the proposed fix here makes that work but crashes on an MPFR test in make test-all:
Clearly I did something wrong, but I'm out of ideas, so there goes my great plan to fix this myself :)
Example C code:
Example Julia code: