Jump to content

Generate Event when VI is aborted


Recommended Posts

Hello there

I have been scratching my head all day thinking if its possible to trigger an event when vi is aborted using the Abort vi button on the toolbar. Couldn't really figure out what to do. Found abort vi method but it just aborts the vi if the part of the code containing this method is executed. Any ideas?

Kind Regards

Austin

Link to post
Share on other sites

The answer is that you can't. The abort button is supposed to stop the VI immediately, without giving you the chance to execute more code and is only supposed to be used in simple throwaway VIs or when debugging. It's not meant to be part of a normal UI or VI execution.

If it's really important to you, you could create your own abort button and call the abort method when you get the event for it, but there is nothing guaranteeing that your code will not be stuck and unable to execute the event.

Link to post
Share on other sites

It rather depends what you want to happen when you press the abort button. I have used the following method to do hardware shut-down after the abort button is pressed during debug.

Simply stated you launch a watchdog VI that waits on a queue when you press the abort button on the main VI this makes the queue invalid so that the error causes the loop to end and any code following the loop to be executed. See the example attached.

Example.zip

  • Like 2
Link to post
Share on other sites
You could use an XControl and monitor the 'Execution State Changed' event.
Hm... I was thinking in terms of monitoring any arbitrary VI, but this is an interesting approach. An XControl gets an event when the owning VI changes state, so if you put an XControl on the front panel of the VI you're interested in, that XControl could fire an event when the owning VI changes state. That avoids the overhead of polling.

The downside is that the XControl is going to force the front panel of the VI to always be in memory, which creates a performance hit when calling the VI since time is spent updating the front panel.

If the VI you're interested in is one that has its front panel visible, this is a good idea. You would create a user event in your monitor VI, pass that user event to the VI-of-interest, which would put that user event refnum into the XControl (probably through the FPTerminal). Then when the XControl gets the "owner went idle", it fires that user event.

Link to post
Share on other sites

Many moons ago I posted a silly VI on the dark side to post a message when a user hit the pause button. It used an XControl to monitor the Is VI Paused property (private).

http://forums.ni.com/t5/LabVIEW/Is-there-a-way-to-know-programatically-when-LabVIEW-has-been/m-p/1320065#M540168

In this case, however, if your VI is in Run mode before execution then I do not believe you will receive the desired State Change Events when it is stopped. To be safe you would have to poll the execution state of the owning VI, probably inside the Facade Timeout case.

I wouldn't let this anywhere near code that I cared about, but perhaps desperate times call for desperate measures.

Edited by Darin
Link to post
Share on other sites

A simple test shows that an XControl gets the 'Execution state change' event when the owning VI is aborted using <ctrl-.> or the 'Abort VI' method.

Ton

Even with the VI in run mode before running? Never tried it but I thought it was run/edit mode changing.

Link to post
Share on other sites

It used to. Now you have to wait for LV to finish scratching its arse (yeah I'm looking at you serial port VIs)

Sometimes I dream about a world where LV could abort CLNs.

Link to post
Share on other sites

Sometimes I dream about a world where LV could abort CLNs.

I maybe just remembering through rose tinted spectacles, but I believe LV 7 could

No, CLNs were never abortable. Once you're out of LV's execution system, there's nothing LV can do but wait for the code to return control to us.

Actually since about LabVIEW 8.2 they sort of are through the badly named Callback functions.

LabVIEW 7 didn't have that but CINS had a CINAbort function that could do that, if properly implemented.

Link to post
Share on other sites

Actually since about LabVIEW 8.2 they sort of are through the badly named Callback functions.

LabVIEW 7 didn't have that but CINS had a CINAbort function that could do that, if properly implemented.

I didn't count "signal-able" as the same as abortable.
Link to post
Share on other sites

Actually since about LabVIEW 8.2 they sort of are through the badly named Callback functions.

LabVIEW 7 didn't have that but CINS had a CINAbort function that could do that, if properly implemented.

I didn't count "signal-able" as the same as abortable.

Right - don't those just allow you to call another function in your library? In almost every use case I've had where I wanted to abort, it's because the DLL is misbehaving/unresponsive (and naturally has no signalling routine). If LV were to fork (or CreateProcess or CreateThread or however you'd actually implement it) and then call the routine, wouldn't that be a pretty effective way to sandbox the call and make it abortable?

Link to post
Share on other sites

Right - don't those just allow you to call another function in your library? In almost every use case I've had where I wanted to abort, it's because the DLL is misbehaving/unresponsive (and naturally has no signalling routine). If LV were to fork (or CreateProcess or CreateThread or however you'd actually implement it) and then call the routine, wouldn't that be a pretty effective way to sandbox the call and make it abortable?

Well, yes they allow to call another function or more precisely three. One when the CLN is initialized, one when the VI containing the CLN is aborted and one when the CLN is unintialized. Each takes a context parameter that can also be added to the actual function call itself. So in the OnReserve function you create the context with whatever info your function might require, in the function call itself you setup some bookkeeping of some sort to be able to signal the thread to stop, and in the OnAbort you abort the thread, preferably not by killing the process but by correctly signalling whatever is waiting on some external event. OnUnreserve you deallocate and clean up whatever has accumulated during the OnReserve, OnAbort and function calls.

Of course if your DLL is buggy and just hangs somewhere, this signaling won't help, but honestly once you are in there, nothing will really help safe from killing the process. LabVIEW can not even start to guess how to recover properly from such a situation since it has absolutely no control of the stack during the function call. Any attempt to resume after a forced abort is doomed to cause many nasty sideeffects, if it doesn't immediately go into pointer nirvana. And no a DLL interface doesn't specify a certain Exception handling interface at all, and Exception handling very much depends on the used compiler, since each tends to have it's own patent encumbered exception handling mechanisme.

The OnAbort function is responsible to signal the waiting thread and make sure it cleanly exists back to the LabVIEW diagram with properly cleaned up stack and all.

Link to post
Share on other sites

If LV were to fork (or CreateProcess or CreateThread or however you'd actually implement it) and then call the routine, wouldn't that be a pretty effective way to sandbox the call and make it abortable?

If LV ran the call in a separate process, would it be able to share memory? I don't think it can... even if LV allocations could be shared with the process, allocations from that process could not be shared with LV because those allocations would evaporate when the process exited. That would be a pretty hefty penalty for calling libraries if all strings and arrays triggered data copy.

The only real solution would be for all of LV's VIs to run in a separate process from the editor, something that other IDEs do but LV does not because historically it has introduced too many usability issues for which we did not have good solutions. Over the years, various solutions have been found, but at this point, the unity of the execution environment and the dev environment is pretty deeply built in and it would take a rewrite of a substantial part of LV to separate those.

Link to post
Share on other sites

If LV ran the call in a separate process, would it be able to share memory? I don't think it can... even if LV allocations could be shared with the process, allocations from that process could not be shared with LV because those allocations would evaporate when the process exited. That would be a pretty hefty penalty for calling libraries if all strings and arrays triggered data copy.

Urgh, excellent point. It might be possible to dance around this with memory mapping or virtual allocations (in Windows, anyway). It would be an interesting problem to try and solve, but I trust that if it hasn't been done yet, it's either not worth doing or can't be done.

What you say is true, though; anything short of actually separating the IDE from the debugger/RTE/whatever is just a bandage. It would be really cool if we could do that, but it doesn't surprised me that the two are so deeply intertwined at this point.

Link to post
Share on other sites

If LV ran the call in a separate process, would it be able to share memory? I don't think it can... even if LV allocations could be shared with the process, allocations from that process could not be shared with LV because those allocations would evaporate when the process exited. That would be a pretty hefty penalty for calling libraries if all strings and arrays triggered data copy.

The only real solution would be for all of LV's VIs to run in a separate process from the editor, something that other IDEs do but LV does not because historically it has introduced too many usability issues for which we did not have good solutions. Over the years, various solutions have been found, but at this point, the unity of the execution environment and the dev environment is pretty deeply built in and it would take a rewrite of a substantial part of LV to separate those.

And in practice LabVIEW has already the seperation of runtime system and IDE, or otherwise remote target deployment and debugging both with RT and FPGA targets as well as from desktop LabVIEW to desktop LabVIEW would not be possible. But it's not the solution for allowing truely abortable CLNs.

You would have to separate the actual CLN context in order to be able to recover from an aborted CLN and that would mean an isolation of parts of the runtime system inside the runtime system. A pain in the ass to do, and a total performance killer as you have already aluded to about string and array parameters that would trigger copies.

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.