Subject: Re: bug#18592: FFI should have portable access to ‘errno’

From: Mark H Weaver <[email-masked]>
Date: Thu, 13 Nov 2014 12:12:32 -0500

Frank Terbeck <[email-masked]> writes:

> Mark H. Weaver wrote:
>> Frank Terbeck <[email-masked]> writes:
> [...]
>>> Mark Weaver on IRC thought it would be a good idea to add portable
>>> access to the contents of ‘errno’ (however it's actually implemented) to
>>> Guile's FFI. And now the idea has entered the bug tracker. :)
>>
>> Indeed, thanks for filing this ticket.
>>
>> I see a problem with this idea: something (e.g. a system async) might
>> change 'errno' before the Scheme code fetches the 'errno' value.
>
> Yes. Ludovic hinted at the use of ‘call-with-blocked-asyncs’ to avoid
> this. To deal with that, I wrote a macro for guile-termios¹:
>
> (define-syntax-rule (call-with-errno (errno exp) fail0 fail1 ...)
>   (let-values (((failed? errno) (call-with-blocked-asyncs
>                                  (lambda ()
>                                    (let* ((f? (termios-failure? exp))
>                                           (err (if f? (get-errno) 0)))
>                                      (values f? err))))))
>     (if failed?
>         (begin fail0 fail1 ...)
>         #t)))
>
> That seems to work fine, unless I'm missing something.

I looked at guile-termios, and I can see that you've done about as good
a job as could be expected from pure Guile Scheme code today, but even
so, it's neither portable nor future-proof, and might not even work
reliably today.  One potential problem is that memory allocation might
modify 'errno', and in Guile 2.2 even calling a Scheme procedure can
cause memory allocation if the stack needs to be expanded.

With current versions of Guile, I see no good way to check 'errno' using
the Dynamic FFI.  I think the only proper solution today is to write a C
extension that wraps each library function that might set 'errno', and
to have those wrappers check 'errno' immediately after the wrapped
function returns, without using any libguile functions in between.

I intend to have a better solution for this in Guile 2.0.12.

    Regards,
      Mark