I worked out a basic implementation for a thread-local errnohttps://github.com/ffilozov/cffi/compare/thread-local-errno. Bordeaux-threads has been added as a dependency as well as two extra functions: cffi:set-errno and cffi:get-errno.
This is a much cleaner interface than passing an object, and the generated function doesn't need to have an extra parameter.
Sample:
CL-USER> (cffi:defcfun ("socket" :errno t) :int (a :int) (b :int) (c :int)) Warning: :call-direct ignored because :error-value specified. SOCKET
CL-USER> (socket -1 -1 -1) -1
CL-USER> (cffi:get-errno) 22 T
The implementation uses locking, so its efficiency could improved. I'm interested in your suggestions on how to do that.
On Thu, Aug 8, 2013 at 4:29 AM, Daniel Herring dherring@tentpost.comwrote:
Hi Felix,
Errno is a particularly tricky beast. It is a thread-local "global" that is modified by a large number of system calls and library functions. Code must be careful to check it before another such call is made. I could easily imagine a stop-the-world GC accidentally modifying errno if errno is not checked "atomically" with the function call.
Also errno is very lightweight. An extra foreign call to check it could easily dwarf the cost of the check. Errno is a "hidden" return parameter, much like the second position in a multiple-value return.
Thus the Allegro semantics of returning errno as a second value seem reasonable to me.
As you suggested, CFFI could provide a default errno implementation for CLs that have different native semantics.
- Daniel