Aha interesting, so every c-lambda that returns a scheme-object, will check if ___result is set to an error. Does that check trig on all errors, what's its definition.., is it implemented in any particular macro or alike?
Just for me as a user to be able to know exactly.
2016-01-07 5:28 GMT+08:00 Marc Feeley feeley@iro.umontreal.ca:
The code I sent previously already handles heap overflows properly (with raising an exception on the Scheme side). When ___err is not ___FIX(___NO_ERR), the operation failed and the glue code that was generated by the FFI will handle this properly by raising an exception.
As I said, a heap overflow could also happen when the heap limit that the user specified with -:hNNN is reached. But that is not a fatal error because the exception can be caught in Scheme.
Marc
On Jan 6, 2016, at 4:20 PM, Adam adam.mlmb@gmail.com wrote:
Marc,
So what we get to then is that that Scheme object allocation could fail.
In that case, would the mature way of dealing with it for the code return a special error, and then have a Scheme-side exception handler?
Also just to understand - is the only thin that would allocating objects
in the C world to fail, would be that malloc() failed, or are there other more local things that could make the object allocation fail?
(define uint32_tag (lambda (a) (let* ((r ((c-lambda (TIFF* ttag_t) scheme-object " ___U32 val; if (TIFFGetField(___arg1, ___arg2, &val) == 1) { if ((___err = ___U32_to_SCMOBJ (___PSTATE, val, &___result,
___RETURN_POS)) == ___FIX(___NO_ERR)) {
___release_scmobj (___result); } else { ___result = [ SOME ERROR CODE ]; ? } } else { ___result = ___FAL; }
") a))) (if (eq? a some-error-code) (##raise-heap-overflow-exception)
a))
2016-01-06 23:02 GMT+08:00 Marc Feeley feeley@iro.umontreal.ca: On a 64 bit machine all uint32 values fit in a fixnum so there is no
allocation possible. On a 32 bit machine, converting a large uint32 will cause a heap allocation of a bignum. However the code is written so that it detects heap overflows and raises a Scheme exception in that case (the Scheme exception can be handled in Scheme because the GC will have prereserved some room in the heap to do further processing in Scheme).
A Scheme heap overflow exception could be raised by a malloc failure or
if the Scheme heap size limit is reached (see -:h runtime option).
Try
% gsi -:h1000 -e "(let loop ((x 0)) (loop (list x)))" *** ERROR IN (string)@1.1 -- Heap overflow
% gsi -:h1000 -e "(with-exception-catcher (lambda (e) (pp (list 'caught
e))) (lambda () (let loop ((x 0)) (loop (list x)))))"
(caught #<heap-overflow-exception #2>)
Marc
On Jan 6, 2016, at 9:48 AM, Adam adam.mlmb@gmail.com wrote:
2016-01-06 22:37 GMT+08:00 Marc Feeley feeley@iro.umontreal.ca: Of course one way would be to return a double (which has 53 bits of
precision) and use NaN to encode “missing tag”. I’m not kidding!
If you don’t like this approach, and I can understand why you
wouldn’t, then you have to do the conversion to ___SCMOBJ by directly calling the conversion macros. Something like this:
(define uint32_tag (c-lambda (TIFF* ttag_t) scheme-object " ___U32 val; if (TIFFGetField(___arg1, ___arg2, &val) == 1) { if ((___err = ___U32_to_SCMOBJ (___PSTATE, val, &___result,
___RETURN_POS)) == ___FIX(___NO_ERR)) {
___release_scmobj (___result); } } else { ___result = ___FAL; }
"))
Neat! What is the risk involved with this one - I mean, the Scheme
object allocation on the Gambit heap could fail under certain circumstances. But would that only be on malloc() failure?