How to abort evaluation of a sequence of inputs?
Asked Answered
W

3

4

By default pressing Alt+. or calling Abort[] within the evaluation causes abort of the currently evaluating input. But when working in the FrontEnd we usually send to the kernel a sequence of inputs. For example, if we type the following three expressions on separate lines in one Cell and then press Shift+Enter we get infinite evaluation:

f := CheckAbort[Pause[.1], Abort[]]
While[True, f]
While[True, f]
While[True, f]

To stop this infinite evaluation we must to press Alt+. three times.

How to define the function f in the example above in such a way that pressing Alt+. one time will abort the evaluation of the full sequence of inputs without quitting the kernel?

EDIT

I think that if the FrontEnd creates an input queue for MathKernel it probably can also cancel this queue.

Waves answered 11/4, 2011 at 18:20 Comment(5)
I would split the input into four cells.Bedelia
@Sasha, true, however, the behavior extends over several input cells. If you are running multiple calculations sequentially and one fails, it is very difficult to shut it down.Dibranchiate
@Dibranchiate You have explained the primary reason why we need to have a way to STOP evaluation of the whole EvaluationNotebook[] not just the current input line. It is very strange that up to this time we have no way to do this in the FrontEnd! A keyboard combination for this would be VERY useful for many people and it is so easy to implement this! FrontEnd must just cancel unsent input packets queried for sending to the kernel!Waves
And in really we even have no way just to stop evaluation of the current input line securely! Pressing Alt+"." we just send Abort[] command to the kernel but not necessarily terminate evaluation! It would be right design if we would have explicit control over interception of aborts. But we have no such control! Some built-in functions can absorb the abort sent!Waves
it was worse in earlier versions, pre-v.6, if execution got into the rendering loop, i.e. front-end, then it was impossible to abort, period. So, if you had done something wrong, as often indicated by it taking forever, then you had to wait for it to complete, or completely kill it. In later versions, it is a little more responsive to that, but it is still not perfect.Dibranchiate
E
6

Sasha's suggestion to just use four cells is valid, because that's basically what the FrontEnd does anyway, submitting several distinct evaluations to the Kernel. If you insist in using one cell, wrap it in parens (CompoundExpression), which causes those four lines to be treated as one evaluation (note the need for ; too):

(
   f := CheckAbort[Pause[.1], Abort[]];
   While[True, f];
   While[True, f];
   While[True, f]
)

Then, one abort issued will abort the evaluation as a whole.

Eisenstark answered 11/4, 2011 at 19:11 Comment(1)
This approach has at least one disadvantage: we must explicitly wrap every expression we wish to see in the output by Print. However by using CellEvaluationFunction (uncovered by WReach here) we probably could do this automatically.Waves
W
1

I have found a way to do what I want. The only problem is that at this moment I do not know how to check whether the FrontEnd has some pending inputs. I am forced just to wait 1 second. In the most cases it is sufficient time for sending all pending inputs to the kernel but probably not always.

In[1]:= $new$PreRead = False;
AbortAllPendingInputs := 
  AbortProtect[If[! $new$PreRead, $new$PreRead = True;
    $TimeOfAbort = SessionTime[];
    last$PreRead = ToString[Definition[$PreRead], InputForm];
    ClearAll[$PreRead];
    $PreRead := If[TrueQ[SessionTime[] - $TimeOfAbort < 1], "",
       $new$PreRead = False;
       ClearAll[$PreRead];
       If[last$PreRead === "Null", #, 
        ToExpression[last$PreRead]; $PreRead@#]
       ] &;]];

In[3]:= f := CheckAbort[Pause[10], AbortAllPendingInputs; Abort[]]

In[4]:= While[True, f]
While[True, f]
While[True, f]

Out[4]= $Aborted

But I am still looking for more elegant solution. I think that if the FrontEnd creates an input queue for MathKernel it probably can also cancel this queue.

Waves answered 11/4, 2011 at 20:1 Comment(0)
M
1

Alexey, please try this version of your code and tell me if/when it fails:

AbortAllPendingInputs :=
  AbortProtect[
    $new$PreRead = True;
    $TimeOfAbort = SessionTime[];
    last$PreRead = $PreRead;
    $PreRead = 
      If[
         TrueQ[SessionTime[] - $TimeOfAbort < 1], 
         "",
         $new$PreRead = False; $PreRead = last$PreRead; $PreRead[#]
        ] &;
  ] /; ! TrueQ[$new$PreRead]
Metheglin answered 13/4, 2011 at 7:30 Comment(6)
Thank you for more elegant version of my function. But the only fail is related to the fact that sometimes the last input packet is sent later than 1 second after pressing Alt+".". But we can not increase this time constrain because if we do this then sometimes a user can press Shift+Inter before the constrain fires...Waves
If we would have the function I am asking for we could use a combination of $PreRead and $Post to cancel unsent packets in a secure way.Waves
@Alexey I am working on other things right now, and I don't usually dig into the "nuts and bolts" of Mathematica this much. Regarding your overarching problem, did you exhaust the possibility of using Evaluator or CellEvaluationFunction etc., for passing code to the 5.2 kernel?Metheglin
@Metheglin I have not tried CellEvaluationFunction yet. This approach requires modifying EvaluationNotebook[] and changing the default way how Mathematica outputs the results. We also must change the original Cell's content on the fly. I'll think about it.Waves
@Metheglin Regarding your modification of last$PreRead definition. It will work only if $PreRead was defined as OwnValue but not DownValue. And your version can not restore Attributes. I think my original solution is more general.Waves
@Alexey, in review, I agree. I was trying to respond with a "more elegant solution" but I did not give this the time it deserved. I don't know when I'll get around to it, but I will think about your main objective, and see if I have anything to offer.Metheglin

© 2022 - 2024 — McMap. All rights reserved.