Setting up diagnostic error messages in large Mathematica projects - error-handling
Whenever I create a large Mathematica project I run into this problem: Preventing avalanche of runtime errors in Mathematica, i.e., Mathematica's error message are opaque, archaic, and legion.
The idea then is to disable all of Mathematica's own error messages and implement type checking and error messages of your own in every Function and Module. However I have not found a simple and efficient way of doing this and end up with, e.g., some function generating an error 20 function calls deep and then get a whole cascade of error messages all the way back up to the main routine.
How would you set up a simple mechanism for this that only generates one error message at the function that experiences the error and a simple list of the chain of function calls?
EDIT: Since it has come up in a couple of answers; I am specifically looking for something lightweight regarding the output it produces (otherwise I could just stick with Mathematica's error messages) and obviously also lightweight in computational overhead. So while Stack and Trace are definitely light on the overhead, their output in complex projects is not quick to parse and some work needs to be done simplifying it.
YAsI - Yet Another (silly?) Idea ...
Re-reading your question ...
The idea then is to disable all of Mathematica's own error messages and implement type checking and error messages of your own in every Function and Module.
Found this:
$MessagePrePrint = ( #; Print[Stack[_][[;; -5]]]; Abort[]) &
v[x_, y_] := w[x, y];
w[x_, y_] := x/y;
StackComplete#v[1, 0];
During evaluation of In[267]:= {StackComplete[v[1,0]];,
StackComplete[v[1,0]], v[1,0], w[1,0], 1/0, 1/0, Message[Power::infy,1/0]}
Out[267]= $Aborted
conclusion ... Aborts at first message and leaves a "reasonable" stack trace. "Reasonable" means "Should be improved".
But it is completely non-intrusive!
To get the ball rolling here is one idea that I've been toying with; the creation of a pseudo stack.
First make a global variable theStack={} and then in every Function or Module start with AppendTo[theStack,"thisFuncName"] and end with theStack=Most#theStack. Assuming moderate (~a few tens) depth of function calls, this should not add any significant overhead.
Then implement your own typing/error checking and use Print#theStack;Abort[]; on errors.
Refinements of this method could include:
Figuring out a way to dynamically get "thisFuncionName" so that the AppendTo[] can be made into an identical function call for all Functions and Module.
Using Message[] Instead of Print[].
Pushing other important variables / stateful information on theStack.
One attempt to implement #Timo's idea (theStack)
Incomplete and perhaps flawed, but just to keep thinking about it:
Clear["Global`*"];
funcDef = t_[args___] \[CircleMinus] a_ :>
{t["nude", args] := a,
ReleaseHold[Hold[t[args] :=
(If[! ValueQ[theStack], theStack = {}];
AppendTo[theStack, ToString[t]];
Check[ss = a, Print[{"-TheStack->", Evaluate#theStack}];
Print#Hold[a]; Abort[]];
theStack = Most#theStack;
Return[ss])
]]};
v[x_, y_]\[CircleMinus] (Sin# g[x, y]) /. funcDef;
g[x_, y_]\[CircleMinus] x/y /. funcDef;
v[2, 3]
v[2, 0]
Output:
Out[299]= Sin[2/3]
During evaluation of In[295]:= Power::infy: Infinite expression 1/0 encountered. >>
During evaluation of In[295]:= {-TheStack->,{v,g}}
During evaluation of In[295]:= Hold[2/0]
Out[300]= $Aborted
A suggestion for extracting stack, maybe something that relies on Trace?
An example of using Trace below, from Chris Chiasson. This code saves evaluation tree of 1 + Sin[x + y] + Tan[x + y] into ~/temp/msgStream.m
Developer`ClearCache[];
SetAttributes[recordSteps, HoldAll];
recordSteps[expr_] :=
Block[{$Output = List#OpenWrite["~/temp/msgStream.m"]},
TracePrint[Unevaluated[expr], _?(FreeQ[#, Off] &),
TraceInternal -> True];
Close /# $Output;
Thread[
Union#Cases[
ReadList["~/temp/msgStream.m", HoldComplete[Expression]],
symb_Symbol /;
AtomQ#Unevaluated#symb &&
Context#Unevaluated#symb === "System`" :>
HoldComplete#symb, {0, Infinity}, Heads -> True],
HoldComplete]
];
recordSteps[1 + Tan[x + y] + Sin[x + y]]
To answer Samsdram's question, the code below (also from Chris) gives evaluation tree of a Mathematica expression. Here is the post from MathGroup with source code and examples.
(Attributes## = {HoldAllComplete}) & /# {traceToTreeAux, toVertex,
HoldFormComplete, getAtoms, getAtomsAux}
MakeBoxes[HoldFormComplete[args___], form_] :=
MakeBoxes[HoldForm[args], form]
edge[{head1_, pos1_, xpr1_}, {head2_, pos2_, xpr2_}] :=
Quiet[Rule[{head1, vertexNumberFunction#pos1, xpr1}, {head2,
vertexNumberFunction#pos2, xpr2}], {Rule::"rhs"}]
getAtomsAux[atom_ /; AtomQ#Unevaluated#atom] :=
Sow[HoldFormComplete#atom, getAtomsAux]
getAtomsAux[xpr_] := Map[getAtomsAux, Unevaluated#xpr, Heads -> True]
getAtoms[xpr_] := Flatten#Reap[getAtomsAux#xpr][[2]]
toVertex[traceToTreeAux[HoldForm[heldXpr_], pos_]] := toVertex[heldXpr]
toVertex[traceToTreeAux[HoldForm[heldXprs___], pos_]] :=
toVertex#traceToTreeAux[Sequence[], pos]
(*this code is strong enough to not need the ToString commands,but \
some of the resulting graph vertices give trouble to the graphing \
routines*)
toVertex[
traceToTreeAux[xpr_, pos_]] := {ToString[
Short#Extract[Unevaluated#xpr, 0, HoldFormComplete], StandardForm],
pos, ToString[Short#First#originalTraceExtract#{pos}, StandardForm]}
traceToTreeAux[xpr_ /; AtomQ#Unevaluated#xpr, ___] := Sequence[]
traceToTreeAux[_HoldForm, ___] := Sequence[]
traceToTreeAux[xpr_, pos_] :=
With[{lhs = toVertex#traceToTreeAux[xpr, pos],
args = HoldComplete ## Unevaluated#xpr},
Identity[Sequence][
ReleaseHold[
Function[Null, edge[lhs, toVertex##], HoldAllComplete] /# args],
ReleaseHold#args]]
traceToTree[xpr_] :=
Block[{vertexNumber = -1, vertexNumberFunction,
originalTraceExtract},
vertexNumberFunction[arg_] :=
vertexNumberFunction[arg] = ++vertexNumber;
originalTraceExtract[pos_] :=
Extract[Unevaluated#xpr, pos, HoldFormComplete]; {MapIndexed[
traceToTreeAux, Unevaluated#xpr, {0, Infinity}]}]
TraceTreeFormPlot[trace_, opts___] :=
Block[{$traceExpressionToTree = True},
Through#{Unprotect, Update}#SparseArray`ExpressionToTree;
SparseArray`ExpressionToTree[trace, Infinity] = traceToTree#trace;
With[{result = ToExpression#ToBoxes#TreeForm[trace, opts]},
Through#{Unprotect, Update}#SparseArray`ExpressionToTree;
SparseArray`ExpressionToTree[trace, Infinity] =.;
Through#{Update, Protect, Update}#SparseArray`ExpressionToTree;
result]];
TraceTreeFormPlot[Trace[Tan[x] + Sin[x] - 2*3 - 55]]
Perhaps we have been over thinking this. What if we just tweaked the pattern matching on the arguments a little. For instance, if we modified the function to check for a numeric quantity and added some code to print an error if it fails. For instance,
TypeNumeric[x_] := If[! NumericQ[Evaluate[x]],
Print["error at "]; Print[Stack[]]; Print["Expression "]; Print[x]; Print["Did
not return a numeric value"];Return[False],
(*Else*)
Return[True];]
SetAttributes[TypeNumeric, HoldAll];
Step 2: If you have a function, f[x_] that requires a numeric quantity, just write it with the standard pattern test and all should be well
Input:
f[x_?TypeNumeric] := Sqrt[x]
f[Log[y]]
f[Log[5]]
Output:
error at
{f}
Expression
Log[y]
Did not return a numeric value
f[Log[y]]
Sqrt[Log[5]]
I believe this will work and, it makes robust type checking as simple as a writing a function or two. The problem is that this could be hugely inefficient because this code evaluates the expression x twice, once for the type checking and once for real. This could be bad if an expensive function call is involved.
I haven't figured out the way around this second problem and would welcome suggestions on that front. Are continuations the way out of this problem?
Hope this helps.
Related
How to work out how game players are cheating?
Before ask my question, I have to explain you my project and how I'm working. I make a server for a game. This server need a lot of development, 800k lines of code. After more than one month. It appears there is a cheat some players are using to destroy player's fun. I have to admit it's a bit hard for me to figure out how to defend myself about this. The server owners community are just under attack too much and everyone is trying to defend himself as they can. I'm working in Lua, JSON, HTML and CSS for this project, 99% Lua. What things the game client has control over : The client can do commands but commands are only allowed to admin. Except if the injection of his own file make a new command. And can inject code inside the client game(explain after). What the server does : I guess, here is where we may can do something. All servers have tons of mods installed, so all client are downloading all my mod/client scripts to trigger my servers events. What is the process of sending a command : the client can use chat /command [attribut][attribut2] the client can run the client's console and : command [attribut][attribut2] How cheaters are doing it? 1) Injector hidden in the memory with windows executable. 2) They are loading a client file to make clients commands to call server triggers*. (because, yes, it's poor everyone is using same scripts so it's known triggers names) *) To do that they open a client console and writing inside : "exec c:/filename.lua" ) 50% of cheat scripts are obfuscated with AHCI & variable replacement like the following. What does a cheat look like? I cannot post the full code here >Body is limited to 30000 characters; you entered 208906.< >obfuscated< >not indented(1 ligne)< -A global function : function IllIlllIllIlllIlllIlllIll(IllIlllIllIllIll) if (IllIlllIllIllIll==(((((919 + 636)-636)*3147)/3147)+919))end end) -A global variable : IllIIllIIllIII(IllIIIllIIIIllI(IlIlIlIlIlIlIlIlII,IIIIIIIIllllllllIIIIIIII))() -A global variable : Xxxxx5 = {} -A global variable : Xxxxx5.debug = true -A local variable : local logged = true Where I need you help I would like to detect not the injection. But, I have no control at all, on this. I would like to detect one of these thing : (Remember I can inject my client lua / Json scripts to do things) when someone is typing : exec in the console ? when someone is using a global variable/function ? (since I got them "Xxxxx5.debug = true") when someone is trying to detect or scan my triggers ? something I didn't think yet ? Detect if function exists ? I have global and local function in the client script : local function d(e) local f = {} local h = GetGameTimer() / 200 f.r = math.floor(math.sin(h * e + 0) * 127 + 128) f.g = math.floor(math.sin(h * e + 2) * 127 + 128) f.b = math.floor(math.sin(h * e + 4) * 127 + 128) return f end function Dt(text, x, y) ..stuff end A good information is : I succeed to do a good protection but it's very basic.... Most of cheats are using the same commands to be oppened. I just patched the shordcuts to acces them. Client get kick if they use them. Maybe it's a solution if better coded ? But, if player is in the chat or console it's no more working so I don't figure out how it's working when player is in this state. (Key disabled) Why I'm asking for help ? I can assure I dev all my scripts, reworked all my downloaded scripts, find all other solutions, without any help. I prefer learn to fish than ask for a fish. But this time tried many things that are not working. What I've tried : no one of these conditions worked : -- if (_G["Xxxxx.IsMenuOpened"] ~= nil) then -- while true do -- print = 'Xxxxx' -- end -- end -- if Xxxxx ~= nil then -- setfenv(Xxxxx , nil ) -- end -- if rawget( _G, Xxxxx) ~= nil then -- "var" n'est pas déclaré -- print 'Xxxxx DETECTER !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' -- end -- if rawget( _G, Xxxx) ~= nil then -- "var" n'est pas déclaré -- print 'Xxxxx DETECTER !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' -- end -- if (_G["Xxxx.IsAnyMenuOpened"] ~= nil) then -- while true do -- print = 'Xxxxx' -- end -- print = 'xxxxx' -- end -- if source == '[Xxxx]' or source == 'Xxxxx' then -- while true do -- print = 'Xxxxx' -- end -- print = 'xxxxx' -- end -- if (_G["Xxxxx"] ~= nil) then -- while true do -- print = 'Xxxxx' -- end -- print = 'xxxxx' -- end -- if Xxxxx ~= nil or Lynx8.debug = true or Lynx8.debug = false then -- reason2 = 'Xxxxx DETECTE' -- TriggerServerEvent("Drop_player" , reason2 ) -- end -- if Xxxxx.Display() ~= nil then -- reason2 = 'Xxxxx DETECTE' -- TriggerServerEvent("Drop_player" , reason2 ) -- end
After more research... Here I come maybe with a good solution. I have most of used cheats in my possession. So all of them have global variable and function. So I searched may there is a way to lock Global variable by using and locking them before cheaters. http://lua-users.org/lists/lua-l/2003-08/msg00081.html So, injection will fail because used variable will be lockeD. I read this : And It look's it's a good solution for me yes. Now I have more precise questions, may you can help me with this : I don't know multiples things : $ cat z.lua This come from the pasted url. What's this ? Cound you confirm ? In lua Or Json, Is there a way to lock variable before use ?
Dymola Results of checkModel()
checkmodel([Some Model]) opens the GUI "Dymola Messages", tab "Translation" and displays Errors, Warnings, and Messages. Does anyone know how to write these infos to a logfile or get them as kind of return value of checkModel(). All I've found in the documentation was, that checkModel() only returns a success-boolean. Are these infos saved temporarily somewhere? Note, that I only want to apply checkModel() but not actually translating the code.
I finally found a solution at least for Dymola 2016 and newer, so if someone is interested - here it is (it is not very user-friendly, but it works): The key-command is getLastError() which not only returns the last error (as one could think...), but all errors that are detected by checkModel() as well as the overall statistics. All informations are sampled in one string, in which the last lines looks like: "[...] Local classes checked, checking <[Some Path]> ERROR: 2 errors were found WARNING: 13 warnings were issued = false " Following operations will return the number of actual errors (for warnings it is more or less the same): b = checkmodel([Some Model]) s = getLastError() ind1 = Modelica.Utilities.Strings.findLast(s,"ERROR:") ind2 = Modelica.Utilities.Strings.findLast(s," errors were found") nErrors = Modelica.Utilities.Strings.substring(s,ind1+6,ind2) //6 = len(ERROR:) nErrors = Modelica.Utilities.Strings.replace(nErrors," ","") nErrors = "2" Note: I used findLast as I know, that the lines of interest are at the very end of the string. So this is significantly faster than using find This only works, if the line "ERROR: ...." actually exists. Otherwise, the substring call will throw an error. Of course this could be done in less lines, but maybe this version is easier to read. NOTE: This will only works with Dymola 2016 and newer. The return-string of getLastError is of a different structure in Dymola 2015 and older.
The following should handle it: clearlog(); // To start fresh Advanced.TranslationInCommandLog=true; checkModel(...); savelog(...); This is mentioned in the Dymola User Manual Volume 1, section "Parameter studies by running Dymola a number of time in “batch mode”" on pg 630 or so.
What's the equivalent of moment-yielding (from Tornado) in Twisted?
Part of the implementation of inlineCallbacks is this: if isinstance(result, Deferred): # a deferred was yielded, get the result. def gotResult(r): if waiting[0]: waiting[0] = False waiting[1] = r else: _inlineCallbacks(r, g, deferred) result.addBoth(gotResult) if waiting[0]: # Haven't called back yet, set flag so that we get reinvoked # and return from the loop waiting[0] = False return deferred result = waiting[1] # Reset waiting to initial values for next loop. gotResult uses # waiting, but this isn't a problem because gotResult is only # executed once, and if it hasn't been executed yet, the return # branch above would have been taken. waiting[0] = True waiting[1] = None As it is shown, if in am inlineCallbacks-decorated function I make a call like this: #inlineCallbacks def myfunction(a, b): c = callsomething(a) yield twisted.internet.defer.succeed(None) print callsomething2(b, c) This yield will get back to the function immediately (this means: it won't be re-scheduled but immediately continue from the yield). This contrasts with Tornado's tornado.gen.moment (which isn't more than an already-resolved Future with a result of None), which makes the yielder re-schedule itself, regardless the future being already resolved or not. How can I run a behavior like the one Tornado does when yielding a dummy future like moment?
The equivalent might be something like a yielding a Deferred that doesn't fire until "soon". reactor.callLater(0, ...) is generally accepted to create a timed event that doesn't run now but will run pretty soon. You can easily get a Deferred that fires based on this using twisted.internet.task.deferLater(reactor, 0, lambda: None). You may want to look at alternate scheduling tools instead, though (in both Twisted and Tornado). This kind of re-scheduling trick generally only works in small, simple applications. Its effectiveness diminishes the more tasks concurrently employ it. Consider whether something like twisted.internet.task.cooperate might provide a better solution instead.
ring server messages not traversing ring
I've almost implemented the well-known ring server, however the messages do not seem to be traversing the ring - here's my code: module(ring). -import(lists,[duplicate/2,append/1,zip/2,nthtail/2,nth/2,reverse/1]). -export([start/3,server/0]). start(M,N,Msg)-> start(M,N,[],Msg). start(0,0,_,_)-> ok; start(M,0,PList,Msg)-> nth(1,PList)!nthtail(1,reverse(zip(append(duplicate(M,PList)),duplicate(M*length(PList),Msg)))); start(M,N,PList,Msg)-> start(M,N-1,[spawn(ring, server, [])|PList],Msg). server()-> receive []-> ok; [{Pid,Msg}|T]-> io:format("~p,~p~n",[self(),Msg]), Pid!T; terminate-> true end. it returns the following when executed: 2> ring:start(3,3,"hello"). <0.42.0>,"hello" <0.41.0>,"hello" [{<0.41.0>,"hello"}, {<0.42.0>,"hello"}, {<0.40.0>,"hello"}, {<0.41.0>,"hello"}, {<0.42.0>,"hello"}, {<0.40.0>,"hello"}, {<0.41.0>,"hello"}, {<0.42.0>,"hello"}] May I ask where I am going wrong here? I've checked the zipped process list, and it seems as if it should work. Thanks in advance.
There are 2 mistakes here, the main one is that you do not recursively recall server after printing the message. The second one is that you should not remove the head of your list when you build the first message, otherwise you will have only m*n - 1 messages passed. this code works, but it leaves all the processes active, you should enhance it to kill all processes at the end of the "ring": -module(ring). -import(lists,[duplicate/2,append/1,zip/2,nthtail/2,nth/2,reverse/1]). -export([start/3,server/0]). start(M,N,Msg)-> start(M,N,[],Msg). start(0,0,_,_)-> ok; start(M,0,PList,Msg)-> nth(1,PList)!reverse(zip(append(duplicate(M,PList)),duplicate(M*length(PList),Msg))); start(M,N,PList,Msg)-> start(M,N-1,[spawn(ring, server, [])|PList],Msg). server()-> receive []-> ok; [{Pid,Msg}|T]-> io:format("In Server ~p,~p~n",[self(),Msg]), Pid!T, server(); terminate-> true end. On my side, I don't use import, I find it more explicit when I have lists:reverse..., You can use hd/1 to get the first element of a list, and you could use list comprehension to generate your list of {Pid,Msg}
Your processes are terminating, not looping (and there is never a condition under which they will receive 'terminate'). To solve the termination issue, have them spawn_link instead of just spawn so that when the first one dies, they all die. It is good to kick things off by messaging yourself, to make sure you're not stripping the first message entirely. -module(ring). -import(lists,[duplicate/2,append/1,zip/2,nthtail/2,nth/2,reverse/1]). -export([start/3,server/0]). start(M, N, Msg)-> Scroll = start(M, N, [], Msg), self() ! Scroll. start(0, 0, _, _)-> ok; start(M, 0, PList, Msg)-> nth(1, PList) ! nthtail(1, reverse(zip(append(duplicate(M, PList)), duplicate(M * length(PList), Msg)))); start(M, N, PList, Msg)-> start(M, N - 1, [spawn_link(ring, server, []) | PList], Msg). server()-> receive []-> ok; [{Pid, Msg} | T]-> io:format("~p,~p~n", [self(), Msg]), Pid ! T, server() end. This produces: 1> c(ring). {ok,ring} 2> ring:start(3,3,"raar!"). <0.42.0>,"raar!" <0.41.0>,"raar!" [{<0.41.0>,"raar!"}, {<0.42.0>,"raar!"}, {<0.40.0>,"raar!"}, {<0.41.0>,"raar!"}, {<0.42.0>,"raar!"}, {<0.40.0>,"raar!"}, {<0.41.0>,"raar!"}, {<0.42.0>,"raar!"}] <0.42.0>,"raar!" <0.40.0>,"raar!" <0.41.0>,"raar!" <0.42.0>,"raar!" <0.40.0>,"raar!" <0.41.0>,"raar!" As expected. Note that I'm calling server() again on receipt of a message. When the empty list is received they all die because they are linked. No mess. Some spacing for readability would have been a little more polite. Erlangers usually aren't so leet that we want to plow through a solid mass of characters -- and this actually causes errors with a few operators in some edge cases (like in map syntax). Also, using imported functions is a little less clear. I know is gums up the code with all that namespace business, but its a lifesaver when you start writing larger programs (there are a lot of list operations in the erlang module -- so some of this importing is unnecessary anyway http://www.erlang.org/doc/man/erlang.html#hd-1).
Handling Lua errors in a clean and effective manner
I'm currently trying to code an add-on the popular game World Of Warcraft for a friend. I don't understand too much about the game myself and debugging it within the game is difficult as he's having to do all the testing. I'm pretty new to Lua, so this may be a very easy question to answer. But when a Lua error occurs in WoW it throws it on screen and gets in the way, this is very bad to a game player as it will stop their gameplay if it throws the exception at the wrong time. I'm looking for a way to cleanly handle the error being thrown. Here's my code so far for the function. function GuildShoppingList:gslSlashProc() -- Actions to be taken when command /gsl is procced. BankTab = GetCurrentGuildBankTab() BankInfo = GetGuildBankText(BankTab) local Tabname, Tabicon, TabisViewable, TabcanDeposit, TabnumWithdrawals, remainingWithdrawals = GetGuildBankTabInfo(BankTab) p1 = BankInfo:match('%-%- GSL %-%-%s+(.*)%s+%-%- ENDGSL %-%-') if p1 == nil then self:Print("GSL could not retrieve information, please open the guild bank and select the info tab allow data collection to be made") else self:Print("Returning info for: "..Tabname) for id,qty in p1:gmatch('(%d+):(%d+)') do --do something with those keys: local sName, sLink, iRarity, iLevel, iMinLevel, sType, sSubType, iStackCount = GetItemInfo(id); local iSum = qty/iStackCount self:Print("We need "..sLink.." x"..qty.."("..iSum.." stacks of "..iStackCount..")") end end end The problem being when checking to see if p1 is nil, it still throws a Lua error about trying to call p1 as nil. It will be nil at times and this needs to be handled correctly. What would be the correct most efficient way to go about this?
You might want to wrap your function in a pcall or xpcall which enables you to intercept any error thrown by Lua. Aside of that, I personally find this construct easier to read: p1=string.match(str,pat) if p1 then -- p1 is valid, eg not nil or false else -- handle the problems end