module Roby::Coordination::Models::FaultHandler
Definition of a single fault handler in a FaultResponseTable
Public Instance Methods
@api private
Activate this fault handler for the given exception and arguments. It creates the {FaultHandlingTask} and attaches the handler on it as an action script.
@param [ExecutionException] exception @param [Hash] arguments
# File lib/roby/coordination/models/fault_handler.rb, line 183 def activate(exception, arguments = Hash.new) locations = find_response_locations(exception.origin) if locations.empty? Roby.warn "#{self} did match an exception, but the response location #{response_location} does not match anything" return end plan = exception.origin.plan # Create the response task plan.add(response_task = FaultHandlingTask.new) response_task.fault_handler = self new(response_task, arguments) response_task.start! locations.each do |task| # Mark :stop as handled by the response task and kill # the task # # In addition, if origin == task, we need to handle the # error events as well task.add_error_handler response_task, [task.stop_event.to_execution_exception_matcher, execution_exception_matcher].to_set end locations.each do |task| # This should not be needed. However, the current GC # implementation in ExecutionEngine does not stop at # finished tasks, and therefore would not GC the # underlying tasks task.remove_children(Roby::TaskStructure::Dependency) task.stop! if task.running? end end
Try the repaired action again when the fault handler successfully finishes
It can be called anytime in the script, but will have an effect only at the end of the fault handler
# File lib/roby/coordination/models/fault_handler.rb, line 57 def carry_on __carry_on(true) terminal end
@return [Boolean] if true, the last action of the response
will be to retry whichever action/missions/tasks have been interrupted by the fault
# File lib/roby/coordination/models/fault_handler.rb, line 26 def carry_on?; !!__carry_on end
@return [FaultResponseTable] the table this handler is part of
# File lib/roby/coordination/models/fault_handler.rb, line 10 def fault_response_table; action_interface end
# File lib/roby/coordination/models/fault_handler.rb, line 155 def find_response_locations(origin) if response_location == :origin return [origin].to_set end predicate = if response_location == :missions proc { |t| t.mission? && t.running? } elsif response_location == :actions proc { |t| t.running? && t.planning_task && t.planning_task.kind_of?(Roby::Actions::Task) } end search_graph = origin.plan. task_relation_graph_for(TaskStructure::Dependency). reverse visitor = ResponseLocationVisitor.new(search_graph, predicate) search_graph.depth_first_visit(origin, visitor) {} visitor.selected end
# File lib/roby/coordination/models/fault_handler.rb, line 42 def locate_on_actions response_location :actions self end
# File lib/roby/coordination/models/fault_handler.rb, line 37 def locate_on_missions response_location :missions self end
# File lib/roby/coordination/models/fault_handler.rb, line 47 def locate_on_origin response_location :origin self end
Replace the response's location by this task when the fault handler script is finished
It terminates the script, i.e. no instructions can be added after it is called
@raise ArgumentError if there is already a replacement task
# File lib/roby/coordination/models/fault_handler.rb, line 121 def replace_by(task, until_event = nil) __carry_on(false) replacement_task = validate_or_create_task(task) start replacement_task instructions << ReplaceBy.new(replacement_task) wait(until_event || replacement_task.success_event) instructions << FinalizeReplacement.new emit success_event terminal end
# File lib/roby/coordination/models/fault_handler.rb, line 33 def to_s "#{fault_response_table}.on_fault(#{execution_exception_matcher})" end
@deprecated use {#carry_on}
# File lib/roby/coordination/models/fault_handler.rb, line 63 def try_again; carry_on end
@deprecated use {#carry_on?}
# File lib/roby/coordination/models/fault_handler.rb, line 28 def try_again?; carry_on? end