[GAP Forum] Handling Errors Automatically?
Max Horn
max at quendi.de
Mon Nov 23 16:05:48 GMT 2015
> On 23 Nov 2015, at 11:49, Stephen Linton <sl4 at st-andrews.ac.uk> wrote:
>
> Dear Andrew,
>
> I think what you need is to set BreakOnError to false, as well as possibly setting OnBreak to what you want.
> The messages may still be a bit ugly, but it should do what you need.
Hmm, I would expect that some more work is needed -- for similar problems, I have made extensive use of the undocumented (bug highly useful) function "CALL_WITH_CATCH", combined with setting BreakOnError to false (and resetting it to its previous value afterwards).
Before I give some example code, let me point out another caveat that was not mentioned so far: You were talking about out of memory errors. For these, the strategy suggested by other (and which the example below also uses) is NOT a particular good one. The reason is that when you encounter an out-of-memory error, GAP increases its heap space (I think for now it doubles it). It always does that, before the error handling (it has to -- otherwise, the error handler cannot run, as it also needs memory).
Thus, GAP will eat more and more memory, with each out-of-memory error. If you need to handle dozens or more of this, this quickly gets impractical. Hence, for my own large-scale computations of this kind, I deal with this in a different way. There, I need to compute results for millions (billions?) of inputs, and a couple thousand of them will lead to OOM errors initially). What I am doing is this: The computations are distributed over multiple machines. On each, a shell script runs a GAP instance. The instances are set up to quit when there is an error (instead of the break loop); when that happens, the shell script just restarts GAP -- thanks to suitable bookkeeping, the computations resumes at the next group, and the logs contain a marker telling me whether / which cases failed. The bookkeeping in my context is actually a bit complicated (GAP communicates with a central server via SCSP), but for a single machine setup, one can simply use a text file, with one line for each task -- when a task starts, its id is added to the file, when it is finished, the the result is stored in another file. This way, I can see which tasks started, and which actually finished. When the GAP script starts, it reads in the first file, to find out which problems already are "done".
This approach deals with memory issues, and also makes sure that I never continue computations with inconsistent internal state.
Anyway, if you only expect a small number of these error, or if you mainly need to deal with other kinds of errors, you could use (a variation of) the following snippet, using the UNDOCUMENTED function CALL_WITH_CATCH
CallWithErrorHandling := function(f, args)
local old, result;
old := BreakOnError;
BreakOnError := false;
result := CALL_WITH_CATCH(f, args);
BreakOnError := old;
if result[1] = false then
return fail; # an error occurred
fi;
return result[2]; # return actual result
end;
Then, replace e.g.
x := f(a,b,c)
by
x := CallWithErrorHandling(f,[a,b,c]);
Of course the above code makes various assumptions, e.g. it assumes the
function being called returns something, etc. -- but you should be able to modify
it to do what you need.
But remember: This is using an UNDOCUMENTED GAP function, so it may
break in the future -- though right now that seems unlikely.
Cheers,
Max
More information about the Forum
mailing list