MLton / mlton

The MLton repository
http://mlton.org
Other
960 stars 127 forks source link

FFI causing segmentation faults #572

Closed hummy123 closed 4 months ago

hummy123 commented 4 months ago

Hi there.

I did some experimenting with MLton and its FFI mechanism recently and am happy I have a good idea about how to complete the small project I would like to build with it. There's an odd issue I encountered, but I was able to get around it by moving a little code from SML to C (which is fine).

I thought it would be worth mentioning as documentation for others and if it's deemed an issue worth fixing.

Basically, the error/segmentation faults I encountered came from trying to set SML callbacks with the GLFW windowing library written in C.

I tried my best to explain the issue in the readme at the following three repositories (which I recommend reading in the listed order):

  1. simple-mlton-glfw-callback a. This repository contains code for a program which prints "hello from mlton" to the terminal whenever a key is pressed while the window is focused. Has no issues (at least on aarch64-linux).
  2. box-x-box-c-callback a. This contains a more complicated program. It defines a key callback in C which moves one of the boxes on the screen in response to the i, e, j, k, l keys. Has no issues either.
  3. box-x-box-sml-callback a. An edit of the c-callback repository at item list (2) which is meant to print "hello from mlton" when a key is pressed. This one defines a callback from SML and exports it to C. Strangely, the segfault disappears if I remove calls to pure functions which have nothing to do with FFI whatsoever. The readme has more details.

I hope my description of the issue is clear. I'm not sure what else to say, but I'm happy with writing minimal callback code in C so it's not an issue for me personally.

I would be interested in hearing if the segfault occurs for others. I'm on a somewhat uncommon platform (aarch64-linux) and it might be that the segfault is specific to this platform.

pclayton commented 4 months ago

I suspect you are not using reentrant correctly. This keyword is needed for an imported C function in which program control may return back into SML. In your program, control starts in the SML main function. In a call to which C function does program control return from C back to SML?

Knowing nothing about GLFW, I am susprised that Key.setCallback has the reentrant attribute because its name suggests it just registers a callback, but doesn't call the callback. I suspect reentrant is not necessary for that function. Also, Glfw.pollEvents does not have the reentrant keyword. I suspect callbacks to SML may be dispatched from within this function. If so, it must have the reentrant keyword.

hummy123 commented 4 months ago

I suspect you are not using reentrant correctly. This keyword is needed for an imported C function in which program control may return back into SML. In your program, control starts in the SML main function. In a call to which C function does program control return from C back to SML?

Knowing nothing about GLFW, I am susprised that Key.setCallback has the reentrant attribute because its name suggests it just registers a callback, but doesn't call the callback. I suspect reentrant is not necessary for that function. Also, Glfw.pollEvents does not have the reentrant keyword. I suspect callbacks to SML may be dispatched from within this function. If so, it must have the reentrant keyword.

Thanks for the help and for your second note especially. You're right: adding the reentrant keyword to Glfw.pollEvents (in the box-x-box-sml-callback repository) avoided the segfault entirely, and works as expected.

I'm a bit surprised at this solution (the simple-mlton-glfw-callback repository doesn't segfault and also doesn't have reentrant for Glfw.pollEvents) but I'm happy to learn it was my mistake and that I didn't need to impose on others. Thanks again for the help.