Class: PuppetDebugServer::DebugSession::FlowControl

Inherits:
Object
  • Object
show all
Defined in:
lib/puppet-debugserver/debug_session/flow_control.rb

Overview

Manages the flags used to control the flow of puppet and Debugger during a debug session.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(debug_session) ⇒ FlowControl



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/puppet-debugserver/debug_session/flow_control.rb', line 13

def initialize(debug_session)
  @debug_session = debug_session

  @flag_mutex = Mutex.new
  @flags = {
    start_puppet: false,
    puppet_started: false,
    session_paused: false,
    client_completed_configuration: false,
    session_setup: false,
    terminate: false,
    suppress_log_messages: false
  }

  @run_mode = PuppetDebugServer::DebugSession::PuppetSessionRunMode.new
end

Instance Attribute Details

#run_modePuppetDebugServer::DebugSession::PuppetSessionRunMode (readonly)

What mode the debug session is running in



10
11
12
# File 'lib/puppet-debugserver/debug_session/flow_control.rb', line 10

def run_mode
  @run_mode
end

Instance Method Details

#assert_flag(flag_name) ⇒ Object

Asserts a flag is set



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/puppet-debugserver/debug_session/flow_control.rb', line 54

def assert_flag(flag_name)
  @flag_mutex.synchronize do
    @flags[flag_name] = true
    PuppetDebugServer.log_message(:debug, "Asserting flag #{flag_name} is true")
    # Any custom logic for when flags are asserted
    # rubocop:disable Style/MultipleComparison, Style/SoleNestedConditional This is faster and doesn't require creation of an array
    if flag_name == :client_completed_configuration || flag_name == :session_setup
      # If the client_completed_configuration and session_setup flag are asserted but the session isn't active yet
      # assert the flag start_puppet so puppet can start in the main thread.
      if !@flags[:puppet_started] && @flags[:client_completed_configuration] && @flags[:session_setup]
        PuppetDebugServer.log_message(:debug, 'Asserting flag start_puppet is true')
        @flags[:start_puppet] = true
      end
    end
    @terminate_flag = true if flag_name == :terminate
  end
end

#continue!Object

Continues a paused debug session



133
134
135
136
137
# File 'lib/puppet-debugserver/debug_session/flow_control.rb', line 133

def continue!
  run_mode.run!
  @debug_session.puppet_session_state.saved.clear!
  unassert_flag(:session_paused)
end

#flag?(flag_name) ⇒ Boolean

Returns which flags are set.

Available flags :start_puppet Indicates the main thread can start running Puppet and begin the debug session :puppet_started Indicates the main thread has started running puppet and debug session is now active :session_paused Indicates that the debug session has hit a breakpoint and is currently paused :client_completed_configuration The debug client has completed it’s configuration :session_setup This debug session has been setup ready to start :terminate Indicates that all threads and wait processes should terminate :suppress_log_messages Indicates that Puppet log messages should not be sent to the client



43
44
45
46
47
48
49
# File 'lib/puppet-debugserver/debug_session/flow_control.rb', line 43

def flag?(flag_name)
  result = false
  @flag_mutex.synchronize do
    result = @flags[flag_name]
  end
  result.nil? ? false : result
end

#next!Object

Next steps through a paused debug session



140
141
142
143
144
# File 'lib/puppet-debugserver/debug_session/flow_control.rb', line 140

def next!
  run_mode.next!(@debug_session.puppet_session_state.saved.pops_depth_level)
  @debug_session.puppet_session_state.saved.clear!
  unassert_flag(:session_paused)
end

#raise_stopped_event_and_wait(reason, description, text, session_state) ⇒ Object

Raises a stopped event to the Debug Client and waits for the debug session to continue.



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/puppet-debugserver/debug_session/flow_control.rb', line 113

def raise_stopped_event_and_wait(reason, description, text, session_state)
  # Signal a stop event
  assert_flag(:session_paused)

  # Save the state so when the client queries us, we can respond.
  @debug_session.puppet_session_state.saved.update!(session_state)

  @debug_session.send_stopped_event(
    reason,
    'description' => description,
    'text' => text,
    'threadId' => @debug_session.puppet_thread_id
  )

  # Spin-wait for the session to be unpaused...
  # TODO - Could be better. Semaphore maybe?
  sleep(0.5) while flag?(:session_paused) && !terminate?
end

#session_active?Boolean

Whether the debug session has started.



96
97
98
# File 'lib/puppet-debugserver/debug_session/flow_control.rb', line 96

def session_active?
  flag?(:puppet_started)
end

#session_paused?Boolean

Whether the debug session is paused due to breakpoints.



103
104
105
# File 'lib/puppet-debugserver/debug_session/flow_control.rb', line 103

def session_paused?
  flag?(:session_paused)
end

#step_in!Object

Steps into a paused debug session



147
148
149
150
151
# File 'lib/puppet-debugserver/debug_session/flow_control.rb', line 147

def step_in!
  run_mode.step_in!
  @debug_session.puppet_session_state.saved.clear!
  unassert_flag(:session_paused)
end

#step_out!Object

Steps out of a paused debug session



154
155
156
157
158
# File 'lib/puppet-debugserver/debug_session/flow_control.rb', line 154

def step_out!
  run_mode.step_out!(@debug_session.puppet_session_state.saved.pops_depth_level)
  @debug_session.puppet_session_state.saved.clear!
  unassert_flag(:session_paused)
end

#terminate?Boolean

The terminate flag will be queried quite often during spin-wait cycles and it’s basically immutable (i.e. Once set it can not be unset). So to help speed up access just treat it as a normal boolean. This can also stop any deadlocks.



89
90
91
# File 'lib/puppet-debugserver/debug_session/flow_control.rb', line 89

def terminate?
  @terminate_flag
end

#unassert_flag(flag_name) ⇒ Object

Removes/unasserts a flag



76
77
78
79
80
81
82
83
# File 'lib/puppet-debugserver/debug_session/flow_control.rb', line 76

def unassert_flag(flag_name)
  return if flag_name == :terminate # Can never unset the terminate flag

  @flag_mutex.synchronize do
    @flags[flag_name] = false
    PuppetDebugServer.log_message(:debug, "Unasserting flag #{flag_name} is true")
  end
end