Franz support has said that setting :errno-value is the only guaranteed way to get errno. Macros such as without-interrupt, without-scheduling, and with-delayed-interrupts, are not sufficient.
On Thu, Aug 8, 2013 at 5:53 PM, Felix Filozov ffilozov@gmail.com wrote:
I'm not sure what's overwriting errno. What sort of interrupts do you expect could be overwriting errno, and wouldn't they have to go through the same mechanism of writing to errno like any other thread?
Looking into Allegro CL SMP's manual, there's a macro called with-delayed-interruptshttp://www.franz.com/support/documentation/9.0/doc/operators/excl/with-delayed-interrupts.htm, which should prevent interrupts and GC from running. However, the wrong errno was still returned when I used this macro. I will ask Franz if such a macro exists.
I started exploring your second suggestion. I created an errno defstruct (this is what the user passes), in the CFFI package, and I tried passing that structure to the CFFI-SYS layer to be modified, but then I realized that CFFI-SYS doesn't know anything about the CFFI package so it can't modify the structure. So I'm passing a function to CFFI-SYS, which gets called with the returned errno value as an argument. I don't know if I like this callback mechanism.
Also, while reading through the code I noticed that there's some edge cases that would need to be handled. For example %defcfun may make a call to foreign-funcall if the argument types and the returns types are considered call-by-value. What does that mean?
I also don't quite understand what entry-vec is, if that's something that can be ignored for now.
By the way, I closed my pull request since this clearly would need more work.
On Wed, Aug 7, 2013 at 7:44 PM, Luís Oliveira luismbo@gmail.com wrote:
Felix Filozov ffilozov@gmail.com writes:
In Allegro CL, the only safe way to get errno after a foreign function call is to configure the foreign function definition to return it as a second value.
Why does that happen. Is it because interrupt handlers may call functions that overwrite errno?
CFFI doesn't deal with errno. There has been some previous discussion (http://lists.common-lisp.net/pipermail/cffi-devel/2009-January/003017. html) to return errno safely, but doesn't seem like it went anywhere.
Re-reading that was useful. Thanks for the pointer.
To sum that discussion up: it'd nice to have cffi-sys:get-errno plus a cffi-sys:without-3rd-party-messing-of-errno so we can implement errno handling in the portable side of CFFI.
Do you think that cffi-sys:without-3rd-party-messing-of-errno macro is feasible? If not, we'll have to place the abstraction at the %FOREIGN-FUNCALL level as you suggest.
So any library that tries to get errno is potentially broken in Allegro CL. I'm seeing this in practice with lisp-zmq, for example.
Out of curiosity, what's messing with errno in your case?
I'd like to introduce a new option to defcfun and foreign-funcall called :errno.
It would look like this: (foreign-funcall ("strlen" :errno t) :string "foo" :int), or (defcfun (strlen "strlen" :errno t) :int (s :string)).
Calling (strlen) would return two values, the return value of the foreign call, and errno.
In some Lisps, the only way to get errno is to make an additional foreign call. Then perhaps that call could be made by CFFI and returns as the second value.
That makes sense. Except for the second value bit because CFFI types can yield more than one value. Alternatives that pop up:
Return it as the first value. (Probably requires some multiple-value-list mangling which might not be acceptable performance-wise?)
Have the foreign function accept an extra errno argument that takes some structure than can be modified with the errno value.
Not quite happy with either. Any other ideas?
Since CFFI delegates the handling of errno to the implementation, perhaps we could preserve the status quo and not get bugged down in grandiose plans of portability.
CFFI /is/ a grandiose excursion into portability. :-)
Luís