avoid crash and print better error message when gmp calls abort() #34492
Description
gmp sometimes calls abort()
. (For example,this StackOverflow post says "whenever you try to create or calculate a number with more than 231 - 1 limbs (or machine words), GMP will abort.") This can crash sage or result in cryptic error messages.
Unfortunately, it seems that gmp does not provide a good way to trap these errors to provide helpful OverFlow
error messages. (See the discussions here and here.) So this may need an upstream fix. Jeroen Demeyer suggested an approach that could fix this in 2017 on the gmp-discuss mailing list, but it seems that nothing came of it.
Even if we cannot improve the error messages, can we eliminate the crashes by using sig_on()
/ sig_off()
?
This ticket came from a sage-devel discussion that includes the following two examples.
This crashes sage:
sage: def binnk3u(n,k): return (n/k)**(k))
sage: n1=(2*10**3)
sage: d0=29004853178239
sage: n0=SR(log(n1))
sage: tt=binnk3u(n0+d0-1,(d0))
gmp: overflow in mpz type
------------------------------------------------------------------------
(no backtrace available)
------------------------------------------------------------------------
Unhandled SIGABRT: An abort() occurred.
This probably occurred because a *compiled* module has a bug
in it and is not properly wrapped with sig_on(), sig_off().
Python will now terminate.
------------------------------------------------------------------------
~/development/sage94/src/bin/sage-python: line 2: 55217 Abort trap: 6 sage -python "$@"
This should give a better error message:
sage: 2^(2^62)
gmp: overflow in mpz type
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
Input In [1], in <cell line: 1>()
----> 1 Integer(2)**(Integer(2)**Integer(62))
File ~/development/sage94/src/sage/rings/integer.pyx:2191, in sage.rings.integer.Integer.__pow__()
2189
2190 if type(left) is type(right):
-> 2191 return (<Integer>left)._pow_(right)
2192 elif isinstance(left, Element):
2193 return coercion_model.bin_op(left, right, operator.pow)
File ~/development/sage94/src/sage/rings/integer.pyx:2255, in sage.rings.integer.Integer._pow_()
2253
2254 if mpz_fits_slong_p(exp):
-> 2255 return self._pow_long(mpz_get_si(exp))
2256
2257 # Raising to an exponent which doesn't fit in a long overflows
File ~/development/sage94/src/sage/rings/integer.pyx:2287, in sage.rings.integer.Integer._pow_long()
2285 if n > 0:
2286 x = PY_NEW(Integer)
-> 2287 sig_on()
2288 mpz_pow_ui(x.value, self.value, n)
2289 sig_off()
RuntimeError: Aborted
The message "gmp: overflow in mpz type" is printed to stderr
, so some users might not see it, which would make the error messages even more cryptic.
CC: @slel @zimmermann6
Component: basic arithmetic
Keywords: crash, gmp
Issue created by migration from https://trac.sagemath.org/ticket/34492