I few other methods for you to consider:
1) a separate "helper loop": in this, the main loop of the template is a "manager", with a separate loop inside the actor doing the work. The "worker" can be controlled by non-actorish ways (such as an Abort Notifier) by the Manager, which is always capable of handling new messages coming in. This encapsulates the non-actor communication, keeping it local (and understandable). I likely addition to this is a "job queue", to hold the list of actions that the manager queues up for the worker. Here is where one can have job priority, or cancelable jobs. Note that this is different from the "action stack" (what you called a "state machine"). These are different things that are too often combined.
2) Have a "Sequence actor" that does the long actions, which can't itself be aborted, but which acts on hardware via short-to-execute synchronous Request-Reply messages to separate hardware actors. Send the "abort" messages to the hardware actors, putting them into a safe-mode state where they reply to action requests with errors. The first such error message causes the "Sequence actor" to end it's sequence (using standard error-chaining logic). Note that if your stop really is an emergency then this bypassing of your complex higher-level logic to talk directly to low-level hardware actors is actually a lot safer and more easily testable.
3) An asynchronous version of (2), where the "Sequence actor" uses Async Request-Reply for interaction with the Hardware actors. Less flexible than (2), but more properly actorish, in that the Sequence actor is always able to handle messages.
I actually don't mind your abort notifier triggered from outside the actor. This is, as you say, bending the rules for a limited and clear purpose, and for the special case of aborting.
Unfortunately, though, you're dealing with the problem of "state" (true "state", not the actions of a so-called "QSM") and that isn't ever easy.