Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Mathematica is a bit unusual as a programming language because it never stops on messages, regardless of whether the message is an error, a warning or just an informative message. It simply prints the message and continues with evaluation. This can cause an avalanche of messages and unpredictable behaviour (e.g. memory may get filled up, bringing the machine to a halt with swapping---this is what happened to me)

Is there a way to immediately abort when any message is generated?

Requirements:

  1. if a message would be printed, always abort.
  2. if no message would be printed, don't abort.
  3. do print the first message so I have a hint about what went wrong
  4. the mechanism should work with parallel computations and should abort the full evaluation (i.e. main kernel and all parallel kernels)

There are many ways to handle message printing, including On/Off, Quiet, and possibly others (such as setting some system options). The solution should work well with these. I am afraid manually handling all possible situations is too fragile (there's always a chance something got left out).

I found a solution on MathGroup which aborts, but does not print the message.

I suspect there must exist a robust and simple solution because the Debug palette has a "Break on messages" option.

share|improve this question
    
Related stackoverflow link: stackoverflow.com/questions/7987162/… –  Murta Nov 30 at 19:23

5 Answers 5

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

share|improve this answer
    
I just used ParallelEvaluate instead of DistributeDefinitions, and now it works fine in parallel too. I have some ideas why DistributeDefinitions doesn't work here, but the workaround is good enough for now. Please also see groups.google.com/d/msg/comp.soft-sys.math.mathematica/… –  Szabolcs Feb 8 '12 at 18:53
    
Edited with ParallelEvaluate and as you said it works. Thanks for the link –  Rojo Feb 8 '12 at 18:56
    
@Szabolcs, reading your question on your link, when you do x=1;ParallelEvaluate[x], it returns {1,1} because your main kernel evaluates the result {x,x} returned from the parallel kernels, not because x was automatically synched –  Rojo Feb 8 '12 at 19:16
    
Thanks for pointing this out, you are right, ParallelEvaluate does not auto-sync (ParallelEvaluate@Hold@Evaluate[x] can be used for testing). But Parallelize does auto-distribute definitions, so my original problem that I asked about was valid :-) –  Szabolcs Feb 8 '12 at 19:24
    
+1, good stuff! My version does not yet quite work for parallel, and your does. Nice! –  Leonid Shifrin Feb 8 '12 at 19:37

There were some attempts on that in this discussion. I also have this functionality in my debug function posted here

share|improve this answer
    
Which one do you recommend for practical use? It should work in an environment with no front end, and I need to generalize it for parallel evaluation. –  Szabolcs Feb 8 '12 at 18:27
1  
@Szabolcs I did not use ot for parallel, but I was debugging serious staff with debug, like stack traces with depth 30 or 50, digging deep into internal stuff, and it all worked quite well. So, I'd rather extend debug for parallel, because it serves me very well. It also is useful in that it gives you the (sort of a) stack trace. –  Leonid Shifrin Feb 8 '12 at 18:30
    
@belisarius's idea works quite well, I'll take a detailed look at debug (for the future) after I've debugged this thing... –  Szabolcs Feb 8 '12 at 18:34
    
Your debug function looks very useful. There's one big problem though: it breaks on Quieted messages as well. My code, as well as at least some package functions, uses Quiet at certain positions. –  Szabolcs Feb 8 '12 at 18:41
    
@Szabolcs I will look into it –  Leonid Shifrin Feb 8 '12 at 18:49
up vote 32 down vote accepted

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.

share|improve this answer
2  
Caveat: functions such as Reduce, Refine and Solve can pass messages to handlers which have printed=True but are somehow never printed. These include FindMinimum::fmmp and N::meprec, which I'm guessing are harmless. –  Tobias Hagge Mar 28 '13 at 2:14

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.

share|improve this answer
    
Hi Ralph, thanks for the answer! I formatted your code for you. If you would like more information about how to do this yourself, have a look at this page. –  Verbeia Aug 9 '12 at 6:21
    
Thank you verbeia! As you correctly surmised, I could not figure out how to get the code to look right. –  Ralph Dratman Aug 10 '12 at 11:46

The following works pretty well, at least in Mathematica 10:

  1. On the menu bar, go to Evaluation/Debugger Controls/Show Debugger Tools Window.
  2. On the window that pops up, check the box to "Break at Messages"

It will then stop and display a green box around the code that is outputting an error message.

share|improve this answer
    
Actually I was aware of this when asking the question (see the very last paragraph), but I needed a way that doesn't require the front end. It turns out that the method used in the accepted solution is the same the debugger uses. It's good to point out this possibility explicitly though, so +1. –  Szabolcs Oct 30 at 18:01

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.