How to abort on any message generated?

I found a robust solution described in this MathGroup message by Maxim Rytin:

messageHandler = If[Last[#], Abort[]] &

Internal`AddHandler["Message", messageHandler]

This will abort the computation whenever a message would be printed.

It can be turned off using

Internal`RemoveHandler["Message", messageHandler]

Alternatively this can be temporarily applied to a piece of code like this:

Internal`HandlerBlock[
 {"Message", messageHandler},
 (* ... code here ... *)
]

The currently set message handlers can be retrieved using

Internal`Handlers["Message"]

(Internal`Handlers[] will return all existing handlers)

Whenever a message is generated, Hold[message, printed] is passed to all "Message" handler functions where message is the message text and printed is True is the message would be printed, False otherwise.

The debugging palette appears to use the same mechanism to break on messages.


To make it work with parallel evaluations, one can simply register the same handler on all kernels using ParallelEvaluate.


What about something like this?

Function[i, {i, ParallelEvaluate[i]};, HoldFirst][
 Unprotect[Message, Check, Quiet];
 Module[{$guardMes = True, $guardChck = True, $guardQuiet = True},
  Message[args___ /; $guardMes] := Block[{$guardMes = False},
    Message[args];
    If[Head[First@{args}] =!= $Off, Abort[]];
    ];
  Quiet[args___ /; $guardQuiet] := Block[{$guardQuiet = False, $guardMes = False},
     Quiet[args]
    ];
  Check[args___ /; $guardChck] := Block[{$guardChck = False, $guardMes = False},
     Check[args]
    ];
  ]
 ]

EDIT to try to reflect Szabolcs's and Sjoerd's concerns

Function[i, {i, ParallelEvaluate[i]};, HoldFirst][
  Module[{$guardMes = True},
    OnMessageAbort[] := (
      Unprotect[Message];
      Message[args___ /; $guardMes && Head[First@{args}] =!= $Off] :=          
       Block[{$guardMes = False, flag = False},
        Internal`InheritedBlock[{$MessagePrePrint},
         $MessagePrePrint = 
          With[{fn = $MessagePrePrint}, 
           Function[i, flag = True; fn[i], HoldAll]];
         Message[args];
         If[flag, Abort[];]
         ]
        ];
       Protect[Message]);
    OffMessageAbort[] := (
      Unprotect[Message];
      Quiet[
       Message[args___ /; $guardMes && Head[First@{args}] =!= $Off] =.];
      Protect[Message];
      )
    ];
  ];
OnMessageAbort[ker_] := ParallelEvaluate[OnMessageAbort[], ker];
OnMessageAbort[All] := (ParallelEvaluate[OnMessageAbort[]]; 
   OnMessageAbort[]);
OffMessageAbort[ker_] := ParallelEvaluate[OffMessageAbort[], ker];
OffMessageAbort[All] := (ParallelEvaluate[OffMessageAbort[]]; 
   OffMessageAbort[]);

You run that once, and it defines (On/Off)MessageAbort[] in all kernels. You can call OnMessageAbort[] to turn it on on the kernel you run that, or OnMessageAbort[kernel] from the main kernel to turn it on on a particular kernel, just like the second argument to ParallelEvaluate. OnMessageAbort[All] turns it on in all of them. Same goes for OffMessageAbort


The easiest and, so far, the best solution I have found is the following:

(* Put the following two lines at the top of every notebook. *)
messageHandler = If[Last[#], Interrupt[]] & ;
Internal`AddHandler["Message", messageHandler];

The above code is slightly modified from Szabolcs's solution at the beginning of this thread. I changed Abort to Interrupt. The latter seems to work immediately, while it appears that Abort may be waiting for some portion of the evaluation to finish before stopping everything.