[reply redirected to ffi@haskell.org] John Meacham <john@repetae.net> writes:
I may be missing something obvious here, but from the current FFI spec it appears that it is impossible to create libraries in haskell which are meant to be called from c code without running into undefined behavior. The problem is in the definition of hs_init() and hs_exit() . now, it is acceptable to have hs_init and hs_exit called in the initialization and finalization of your library, but the problem arrises when you link against more than one library which is implemented in haskell, suddenly whichever library is initialized secondly segfaults! (or whatever undefined behaviour means.). programs could suddenly stop working when a library is changed from a c implementation to a haskell one, which seems to be a bad thing.
Hmmm, I see what you mean.
proposed fix: allow nested calls to hs_init, hs_exit, a counter is incremented when hs_init is called more than once, and decremented on hs_exit. only the last call to hs_exit will actually do whatever needs to be done.
The hs_init function takes arguments - what if each call to hs_init specifies a different set of arguments? How about: hs_set_hs_argv (int argc, char *argv[]); hs_set_prog_argv (int argc, char *argv[]); hs_init (); hs_exit (); Where: hs_set_hs_argv sets command line parameters for the Haskell runtime system It can be called at most once and that call must be before the first call to hs_init Warning! The flags are not remotely portable between different Haskell runtimes. hs_set_prog_argv sets arguments seen by getProgName and getArgs It can be called at most once and that call must be before the first call to hs_init hs_init initializes the Haskell runtime It can be called multiple times and must be called before the first call to any function exported by the Haskell code. hs_exit finalizes the Haskell runtime hs_init and hs_exit are required to satisfy the usual bracketing rules: 1) At any time, the number of calls that have been made to hs_exit must be no more than the number of calls that have been made to hs_init. 2) If the number of calls to hs_exit is equal to the number of calls to hs_init, then no further calls to hs_init may be made. By the way, the name 'hs_exit' is a little confusing - I expected it to have an ExitCode argument. 'hs_fini' would better match its actual purpose.
note that this cannot be implemented by the programmer himself since there might be several third party libraries also implemented in haskell which an app wishes to link against.
You can implement the modified API (or your modified semantics) quite readily as a little library which you link against your program. All you have to do is tweak the names a little (e.g., s/hs/HS/) to avoid name clashes. -- Alastair Reid reid@cs.utah.edu http://www.cs.utah.edu/~reid/
sorry for the late reply. I did not realize there was an FFI list, seperate from the main haskell one. In any case we should make sure these or similar changes get made, they are pretty much show-stoppers for anyone writing code to the FFI spec as the current spec pretty much makes it impossible to write robust haskell implementatinos of libraries/shared objects. On Sun, Jun 02, 2002 at 06:02:44PM +0100, Alastair Reid wrote:
The hs_init function takes arguments - what if each call to hs_init specifies a different set of arguments? How about:
hs_set_hs_argv (int argc, char *argv[]); hs_set_prog_argv (int argc, char *argv[]); hs_init (); hs_exit ();
Where:
hs_set_hs_argv sets command line parameters for the Haskell runtime system
It can be called at most once and that call must be before the first call to hs_init
Warning! The flags are not remotely portable between different Haskell runtimes.
hs_set_prog_argv sets arguments seen by getProgName and getArgs
It can be called at most once and that call must be before the first call to hs_init
hs_init initializes the Haskell runtime
It can be called multiple times and must be called before the first call to any function exported by the Haskell code.
hs_exit finalizes the Haskell runtime
hs_init and hs_exit are required to satisfy the usual bracketing rules:
1) At any time, the number of calls that have been made to hs_exit must be no more than the number of calls that have been made to hs_init.
2) If the number of calls to hs_exit is equal to the number of calls to hs_init, then no further calls to hs_init may be made.
I really like this change. it would make things much simpler for libraries implemented in haskell which are meant to be called from other languages. however i would make one change, only the first calls to hs_set_hs_argv and hs_set_prog_argv are honored, after that they are ignored, that way if multiple libraries wish to set the arguments it wont run into undefined behavior. (since there is no way in general to know whether hs_set_* has already been called.) also, it should be made clear that it is possible to run the haskell runtime more than once, as in hs_init c + haskell stuff hs_fini c stuff hs_init c + haskell stuff hs_fini done so libraries which are dynamically loaded and unloaded will work.
By the way, the name 'hs_exit' is a little confusing - I expected it to have an ExitCode argument. 'hs_fini' would better match its actual purpose.
I strongly agree, init/fini are definatly pairs.
note that this cannot be implemented by the programmer himself since there might be several third party libraries also implemented in haskell which an app wishes to link against.
You can implement the modified API (or your modified semantics) quite readily as a little library which you link against your program. All you have to do is tweak the names a little (e.g., s/hs/HS/) to avoid name clashes.
The problem is that while this will keep any libraries written by me from stepping on each other, haskell libraries written by someone else will still cause the system to crash when mixed with mine. this is potentially a very bad problem as many systems use dynmaic libraries, it would be bad if they suddenly stopped working because two of them happened to be implemented in haskell. (not to mention a hard to track down bug.) John -- --------------------------------------------------------------------------- John Meacham - California Institute of Technology, Alum. - john@foo.net ---------------------------------------------------------------------------
John Meacham <john@repetae.net>:
however i would make one change, only the first calls to hs_set_hs_argv and hs_set_prog_argv are honored, after that they are ignored, that way if multiple libraries wish to set the arguments it wont run into undefined behavior. (since there is no way in general to know whether hs_set_* has already been called.)
Hmmm, I don't like interfaces that silently ignore arguments. How about if the functions return a bool saying whether arguments got ignored and then the caller can decide whether they care.
also, it should be made clear that it is possible to run the haskell runtime more than once, as in
hs_init c + haskell stuff hs_fini c stuff hs_init c + haskell stuff hs_fini done
so libraries which are dynamically loaded and unloaded will work.
I was deliberately ruling that out. To do this we have to find every single global variable in the Haskell runtimes and provide an initializer function to set them back to their initial values. I'm a little reluctant to add it to the spec because I'm feeling lazy.... -- Alastair
participants (2)
-
Alastair Reid -
John Meacham