LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

How can I dump a call stack when there is an error?

Solved!
Go to solution

"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()?

0 Kudos
Message 1 of 10
(5,447 Views)

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

https://decibel.ni.com/content/groups/large-labview-application-development/blog/2011/02/02/advanced...

 

Best,

Ryan C.
Applications Engineer
National Instruments
0 Kudos
Message 2 of 10
(5,418 Views)

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?

0 Kudos
Message 3 of 10
(5,412 Views)

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.

0 Kudos
Message 4 of 10
(5,407 Views)

@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.

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 5 of 10
(5,403 Views)

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.

0 Kudos
Message 6 of 10
(5,392 Views)
Solution
Accepted by topic author iCat

@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.

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 7 of 10
(5,382 Views)

@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?

0 Kudos
Message 8 of 10
(5,365 Views)

Absolutely! and I tried to explain it in my last post. But ok, since pictures say sometimes more than 1000 words here you go.

 

Stack Trace Generation.png

 

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.

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 9 of 10
(5,361 Views)

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.

0 Kudos
Message 10 of 10
(5,334 Views)