Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Question about monitoring a nested actor to see if it is running or not

I have a HAL interface implemented as an actor. I'm creating a utility that is a bus monitor that shows me information on what's going on with the interface via a GUI window. This utility will be a nested actor in the eyes of the HAL interface actor (which we'll call the "main actor").

This bus monitor shouldn't impact the main actor and I want to start it and shut it down as I please. It receives messages from the interface actor containing the data i want to display on the GUI, meaning the interface actor needs to send it messages.

This is fine if the program was designed to run forever and never stop/start. My concert is trying to come up with a way of having the main actor know that the bus monitor is launched, and if it is launched, send it the data it needs to display. If it is not launched and running, then don't send it this data.

My idea of doing this is by having a boolean in the private data of the main actor, enabling it when launching the nested actor, and disabling it when shutting it down. Then have a check on this boolean when data needs to be sent to the monitor.

Is there a better way of doing this, or is this fine? Is there a function that checks whether a nested actor's enquerer actually leads to an actor that is running? Can I just send messages to an enqueure that doesn't exist and ignore errors?

Thanks!

-Paul

0 Kudos
Message 1 of 7
(5,064 Views)

psammut wrote:

Can I just send messages to an enqueure that doesn't exist and ignore errors?

Thanks!

-Paul

Yes.  If they are just status updates, then you don't need to worry about errors.

Also, a calling actor knows, to within a certain margin of error, if its nested actors are running.  If Launch Nested Actor does not return an error, then the nested actor launched successfully.  When the nested actor stops, the caller will receive a Last Ack message from that actor.  There is a small window of time (likely measured in milliseconds) when the nested actor stops handling messages and the caller receives the Last Ack; if you try to send a message in this window, you will get an error.  Otherwise, you should be good.

Note that this race condition window is unavoidable.  Maintaining a status Boolean doesn't help, because you have to keep it synched with the actual state of your nested actor, and you can't do that without the same potential for race conditions.  So now you are doing extra work, but getting nothing for it.

0 Kudos
Message 2 of 7
(4,591 Views)

I've been doing a "test send" by sending an instance of the base "Message" object.  It's accepted by every actor, and it is effectively a no-op, so even though the receiving actor "executes" it, it's quick and it doesn't affect the receiving actor.

If the attempt to send this no-op throws an error, then I know the receiving actor is dead [now] -- whether I've gotten the Last Ack or not.  (And I may have, but it might be stacked up in my message queue, but the result of sending the no-op tells me immediately.  I.e., no race state, given that you're gauging off the ability to receive messages, and once the queue is destroyed, no more messages are accepted for execution, and all remaining messages in the queue are "dropped".)

I use this in reverse:  I periodically send a no-op to "Caller" (for actors who must have a living Caller), and when that "bounces", I know the application has crashed -- so I have my actor shut down itself and its nested actors.  A watchdog method periodically messages my actors to do this.  I now no longer have zombie actors for applications that crash, so no more having to shut down LabVIEW to clear them. 

0 Kudos
Message 3 of 7
(4,591 Views)

These kinds of operations will tell you if an actor is dead.  It won't tell you if an actor is still alive, only that it was alive when you last sent the heartbeat.

I suppose you could use the Report Error message (with No Error as the data) to the same effect, without having to write a custom message.

0 Kudos
Message 4 of 7
(4,591 Views)

That was my main need: Is my Caller dead (to me)?  If so (and I don't care when that happened), then I need to stop myself.  Because I've effectively become a zombie with no more connection to my original application, so I shouldn't be running.  And since this is duplicated as a core function of every actor in my system, no zombies can live longer than my watchdog period, including any trees of a zombie; they'll all stop themselves automatically.

I could go the other way, and send no-ops to downline actors, then check them off as alive if they respond likewise.  (A flip-flop heartbeat.)  But that use strikes me as being the same as "test a refnum before you use it to see if it's good".  An actor's enqueuer is a refnum (a queue refnum), so the same rule applies:  If you want to know if it's good (i.e., "is the actor alive"), then simply send it what you want to send it.  If the send action throws an error, you know, a priori.  Otherwise, don't worry about it.

I only needed to worry about becoming a zombie process, to prevent the annoying need to power-cycle LabVIEW.

Message 5 of 7
(4,591 Views)

The value of testing a refnum is when you don't want to use, but rather need to do something if it has gone bad.  "Am I a zombie" is such a use (and a valuable one).

0 Kudos
Message 7 of 7
(4,591 Views)