-
-
Notifications
You must be signed in to change notification settings - Fork 415
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
Calling behaviours from bare functions causes seg fault #3013
Comments
The issue here is that your bare function is being called from a non-pony-scheduled thread. This is okay, but you need to register the thread first, which you can do with this FFI function in libponyrt: Lines 471 to 479 in c42ccd3
Can you try adding that FFI call to the top of your callback and see if it works? Once we get your example working we can improve our docs to help with this. fun @callback_func(input: Pointer[U16], output: Pointer[U16], frames: U32, timeInfo: Pointer[U8], flags: U32, data: Any): U8 =>
@pony_register_thread[None]()
try
var out = data as OutStream
@printf[None]("About to call a behaviour...\n".cstring())
out.print("Calling a behaviour.")
@printf[None]("Behaviour was called.\n".cstring())
end
U8(0) |
Unfortunately, adding that call didn't change the outcome at all. The code still seg faults with the behaviour call, and passes without. EDIT: After attempting the suggested modification in my complete project, I found that it does stop the segmentation fault, if the called behaviour has either no arguments passed to it, or only number (int or float) arguments. Thus, in the above it continues to seg fault, but in my complete project, where I was testing a behaviour without any parameters, it passes successfully. Is there any reason why this could be happening? |
Hmmm... if I had to guess without seeing your latest example, I'd guess that there is an issue with allocating new objects using the Pony heap from a non-Pony thread. Is it possible to try your use case without allocating any new objects? |
The following is the bare function from my complete project. I assume when you say "without allocating any new objects", you are referring to the creation of new variable values (e.g fun @def_callback(input_buf: Pointer[I16] iso, output_buf: Pointer[I16], frame_count: U32, timeInfo: Pointer[_PaStreamCallbackTimeInfo], flags: U32, data: Any tag): U8 =>
@pony_register_thread[None]()
try
var l = data as SphinxListener
// TODO Calling a behaviour from this bare function results in a SegFault if non-number args are used.
l.process_chunk(consume input_buf, frame_count)
end
0 |
Sorry, I should have been more specific - I meant things that call the constructors of classes and actors to allocate new objects on the heap. Declaring a local variable of a non-object type like It doesn't look like your current example allocates memory, so now I wonder if it is an issue with tracing the |
Unfortunately, even if the argument has a |
Well, I guess the next step for troubleshooting this is to construct a pthread-based repro for this that can be tested without involving PortAudio. |
Can confirm, Arch Linux, x86_64, using pony v27 (llvm 7.0.1), with SDL_mixer's threads Here's the code that is running into the same issue: |
(@jemc) |
@adri326 I would expect that to crash. You need to call pony_register_thread() |
Forgot about this function; did a push including it, it does not seem to affect anything though |
@adri326 you need to call pony_register_thread in thread_entry. |
@SeanTAllen |
I can't try rn |
Given your small example above, i was able to verify the reason for the segfault:
I was able to run your small example app successfully with the following changes: void* thread_entry(void *param) {
+ pony_register_thread();
printf("B' - 🦓\n");
if (pony_fn == NULL) {
printf("No callback registered?\n");
} else {
pony_fn();
}
- pthread_exit(NULL);
+// pthread_exit(NULL);
} It is important to call this function before calling back into pony code as documented here: https://github.com/ponylang/ponyc/blob/master/src/libponyrt/pony.h#L471:L479 I removed the I hope this helps for getting your portaudio code running. |
Indeed, it does fix the issue. Thanks for the help! |
This was achieved thanks to the guys at Pony: ponylang/ponyc#3013 Turns out you have to call `pony_register_thread` from within your C code, once it enters Pony-territory it is too late.
I'd say yes |
Closing. This is a good topic for the ffi chapter in the tutorial (if it is not covered already). |
While working with PortAudio through the FFI, I found that I wasn't able to call behaviours on actors passed in using the userData field. In the past, I've successfully passed objects using userData fields, and called functions on them, but when I tried a similar action using an actor and a behaviour, it resulted in a Segmentation Fault. I've managed to recreate the bug in the following code snippet:
In the above code example, I expect the callback to print both lines using the FFI printf statements, and the "Calling a behaviour" line to be printed shortly after, however, after the first printf is called, the program seg faults and thus never prints the second line.
The exact output is:
The output of
ponyc -v
is:Please let me know if there's any further information I can provide.
The text was updated successfully, but these errors were encountered: