04-26-2012 08:30 AM - edited 04-26-2012 08:31 AM
"call chain" VI only prints a call stack starting from the VI that contains the call chain VI.
Since I use a SubVI that handles errors and the call chain VI can't be located in the VI where an error occurs,
"call chain" VI is not useful in an error logging VI.
In java, you have Throwable.printStackTrace() that prints the entire call stack.
Does LabVIEW have an equivalent of Throwable.printStackTrace()?
Solved! Go to Solution.
04-27-2012 05:16 PM
Hi iCat,
Please see some of the following links to best error-handling practices. It seems that following some of these strategies might lead to a more organized and elegant solution.
http://zone.ni.com/devzone/cda/tut/p/id/3209
https://decibel.ni.com/content/docs/DOC-17379
https://decibel.ni.com/content/docs/DOC-8592
https://decibel.ni.com/content/docs/DOC-15776
Best,
04-27-2012 06:40 PM
They look good, but still they don't seem to provide a stack trace beginning from the root cause of the error.
Is there anything like Throwable.getStackStrace() in java?
04-27-2012 10:55 PM
The function that generates the error should include the call chain as part of the error text when it creates the error cluster. Otherwise there is no way to trace the error back to the point at which it occurred, because an error in LabVIEW is just data on a wire.
04-28-2012 05:03 AM
@iCat wrote:
"call chain" VI only prints a call stack starting from the VI that contains the call chain VI.
Since I use a SubVI that handles errors and the call chain VI can't be located in the VI where an error occurs,
"call chain" VI is not useful in an error logging VI.
In java, you have Throwable.printStackTrace() that prints the entire call stack.
Does LabVIEW have an equivalent of Throwable.printStackTrace()?
I may have gotten this wrong but if you are concerned about the fact that the Call Chain includes the name of your Error Handler VI it's very easy to delete the first element of the Call Chain array to exclude that name from the list. Otherwise please explain in a different way what you want to do.
04-29-2012 06:06 AM - edited 04-29-2012 06:07 AM
nathand // There is no call chain in the error cluster.
rolfk // The problem is that the first element of the array is at the deepest level of the call chain.
Let's assume that I placed "call chain" VI in D.vi
E.vi invokes D.vi(D<-E).
And the VI tree is "A<-B<-C<-D<-E".
If a VI generated an error in A.vi, "call chain" VI would only return "D.vi" and "E.vi" in the returned array.
I want to see "A.vi", "B.vi", "C.vi", "D.vi", and "E.vi" in the call chain array.
But it's impossible to place "call chain" VI at the lowest level(A.vi in this case) for a large web of VIs.
A.vi could be placed at the second lowest level later in time.
04-29-2012 02:23 PM
@iCat wrote:
nathand // There is no call chain in the error cluster.
rolfk // The problem is that the first element of the array is at the deepest level of the call chain.
Let's assume that I placed "call chain" VI in D.vi
E.vi invokes D.vi(D<-E).
And the VI tree is "A<-B<-C<-D<-E".
If a VI generated an error in A.vi, "call chain" VI would only return "D.vi" and "E.vi" in the returned array.
I want to see "A.vi", "B.vi", "C.vi", "D.vi", and "E.vi" in the call chain array.
But it's impossible to place "call chain" VI at the lowest level(A.vi in this case) for a large web of VIs.
A.vi could be placed at the second lowest level later in time.
WEll you may have to rethink what you expect here. You want to have the same as Structured Exception Handling but besides that there are actually patents on several of those implementations, LabVIEW works a little different since it's all about dataflow. Basically what I do in LabVIEW is to have a VI that is placed where an error could occur. It checks for the error condition and if met adds the actual call stack (Call Chain - the number of levels the error checker uses) plus extra error information into the error cluster. Basically it is what in other languages is the throw statement. All consecutive VIs have this error cluster usually wired through and don't do anything (except the close function which does attempt to close any resources anyhow) if there is an error in. Then at the end of your operation, usually in a higher level VI there is an error handler, that logs the information, shows a dialog or does whatever else makes sense for an error in that context. So your call stack is determined at the point where the error happens but you do not have to code that each time, as you can write a subVI that you can drop into the diagram to handle that for you and add the information to the error cluster.
The error cluster is not exactly the most ideal way to handle structured exception handling but it is a mechanisme that was introduced long ago, and has worked fairly well, or at least not bad enough that many people have worried about trying to find a more universal (and still easy to handle) mechanisme.
05-01-2012 01:57 AM - edited 05-01-2012 01:57 AM
@rolfk wrote:
@iCat wrote:
nathand // There is no call chain in the error cluster.
rolfk // The problem is that the first element of the array is at the deepest level of the call chain.
Let's assume that I placed "call chain" VI in D.vi
E.vi invokes D.vi(D<-E).
And the VI tree is "A<-B<-C<-D<-E".
If a VI generated an error in A.vi, "call chain" VI would only return "D.vi" and "E.vi" in the returned array.
I want to see "A.vi", "B.vi", "C.vi", "D.vi", and "E.vi" in the call chain array.
But it's impossible to place "call chain" VI at the lowest level(A.vi in this case) for a large web of VIs.
A.vi could be placed at the second lowest level later in time.WEll you may have to rethink what you expect here. You want to have the same as Structured Exception Handling but besides that there are actually patents on several of those implementations, LabVIEW works a little different since it's all about dataflow. Basically what I do in LabVIEW is to have a VI that is placed where an error could occur. It checks for the error condition and if met adds the actual call stack (Call Chain - the number of levels the error checker uses) plus extra error information into the error cluster. Basically it is what in other languages is the throw statement. All consecutive VIs have this error cluster usually wired through and don't do anything (except the close function which does attempt to close any resources anyhow) if there is an error in. Then at the end of your operation, usually in a higher level VI there is an error handler, that logs the information, shows a dialog or does whatever else makes sense for an error in that context. So your call stack is determined at the point where the error happens but you do not have to code that each time, as you can write a subVI that you can drop into the diagram to handle that for you and add the information to the error cluster.
The error cluster is not exactly the most ideal way to handle structured exception handling but it is a mechanisme that was introduced long ago, and has worked fairly well, or at least not bad enough that many people have worried about trying to find a more universal (and still easy to handle) mechanisme.
I checked error clusters returned from subVIs made by NI.
The actual call chains were in the error messages of the clusters.
How could I miss that? I think it's because most people including me just skim through the error messages.
What about subVIs made by users but not by NI?
Are they able to generate the actual call stack as NI ones do?
05-01-2012 02:21 AM - edited 05-01-2012 02:24 AM
Absolutely! and I tried to explain it in my last post. But ok, since pictures say sometimes more than 1000 words here you go.
The right side is a function that checks to see if the file exists and if it does attempts to open it in the external viewer that is registered on the computer for this file type. If it doesn't (which is shown here) it generates an error message and puts it in the erorr cluster. The diagram for the VI generating the Call chain is shown on the left. Skip level is used if the actual Call Chain VI might be buried deeper in the hierarchy of error helper VIs to exclude their names which would add no extra information.
For instance building the error cluster could be also put in a subVI if you happen to have that often for instance with API Calls that only return an error code. In that case I have usually a library specific Build Error VI, that receives the error number (usually 0 means success and non-zero is the error code), and creates the Call Chain and then puts that and the error code in the error cluster. It could also incorporate a call to an API to add error specific text information to the error message, if that API supports that.
05-01-2012 12:39 PM
You might also consider using the "Error Cluster from Error Code" function in the Dialog and User Interface Palette. It makes it easy to generate an error cluster and has a "show call chain?" input which will automatically insert the call chain into the error text.