Class: FiberAudit::Runtime::SchedulerObserver

Inherits:
Object
  • Object
show all
Defined in:
lib/fiber_audit/runtime/scheduler_observer.rb

Overview

Explicit-runtime-only hooks for schedulers installed after RUBYOPT boot.

Defined Under Namespace

Modules: FiberHook, SchedulerCloseHook

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(watchdog:) ⇒ SchedulerObserver

Returns a new instance of SchedulerObserver.



80
81
82
83
84
85
86
# File 'lib/fiber_audit/runtime/scheduler_observer.rb', line 80

def initialize(watchdog:)
  @watchdog = watchdog
  @owner_pid = Process.pid
  @active = true
  @mutex = Mutex.new
  @schedulers = {}
end

Instance Attribute Details

#owner_pidObject (readonly)

Returns the value of attribute owner_pid.



78
79
80
# File 'lib/fiber_audit/runtime/scheduler_observer.rb', line 78

def owner_pid
  @owner_pid
end

#watchdogObject (readonly)

Returns the value of attribute watchdog.



78
79
80
# File 'lib/fiber_audit/runtime/scheduler_observer.rb', line 78

def watchdog
  @watchdog
end

Class Method Details

.activate(watchdog:) ⇒ Object



37
38
39
40
41
42
43
44
45
# File 'lib/fiber_audit/runtime/scheduler_observer.rb', line 37

def activate(watchdog:)
  raise RuntimeContractError, 'watchdog must be a FiberAudit::Runtime::Watchdog' unless watchdog.is_a?(Watchdog)

  install_fiber_hook!
  observer = new(watchdog: watchdog)
  @current = observer
  observer.attach_existing!
  observer
end

.deactivate(observer) ⇒ Object



58
59
60
61
# File 'lib/fiber_audit/runtime/scheduler_observer.rb', line 58

def deactivate(observer)
  @current = nil if @current.equal?(observer)
  observer.deactivate
end

.scheduler_changed(previous:, current:, thread:) ⇒ Object



47
48
49
50
51
52
# File 'lib/fiber_audit/runtime/scheduler_observer.rb', line 47

def scheduler_changed(previous:, current:, thread:)
  observer = current_for_process
  return unless observer

  observer.scheduler_changed(previous: previous, current: current, thread: thread)
end

.scheduler_closing(thread:, scheduler: nil) ⇒ Object



54
55
56
# File 'lib/fiber_audit/runtime/scheduler_observer.rb', line 54

def scheduler_closing(thread:, scheduler: nil)
  current_for_process&.scheduler_closing(scheduler: scheduler, thread: thread)
end

Instance Method Details

#active_for_current_process?Boolean

Returns:

  • (Boolean)


88
89
90
# File 'lib/fiber_audit/runtime/scheduler_observer.rb', line 88

def active_for_current_process?
  @active && owner_pid == Process.pid
end

#attach_existing!Object



92
93
94
95
96
# File 'lib/fiber_audit/runtime/scheduler_observer.rb', line 92

def attach_existing!
  scheduler = Fiber.scheduler
  scheduler_installed(scheduler: scheduler, thread: Thread.current) if scheduler
  self
end

#deactivateObject



128
129
130
131
132
# File 'lib/fiber_audit/runtime/scheduler_observer.rb', line 128

def deactivate
  @active = false
  @mutex.synchronize { @schedulers.clear }
  self
end

#scheduler_changed(previous:, current:, thread:) ⇒ Object



98
99
100
101
102
103
104
# File 'lib/fiber_audit/runtime/scheduler_observer.rb', line 98

def scheduler_changed(previous:, current:, thread:)
  return self unless active_for_current_process?

  scheduler_closing(scheduler: previous, thread: thread) if previous && !previous.equal?(current)
  scheduler_installed(scheduler: current, thread: thread) if current
  self
end

#scheduler_closing(thread:, scheduler: nil) ⇒ Object



120
121
122
123
124
125
126
# File 'lib/fiber_audit/runtime/scheduler_observer.rb', line 120

def scheduler_closing(thread:, scheduler: nil)
  return self unless active_for_current_process?
  return self unless untrack_scheduler(scheduler, thread)

  watchdog.scheduler_closing(thread: thread)
  self
end

#scheduler_installed(scheduler:, thread:) ⇒ Object



106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/fiber_audit/runtime/scheduler_observer.rb', line 106

def scheduler_installed(scheduler:, thread:)
  return self unless active_for_current_process? && watchdog.enabled?
  return self unless track_scheduler(scheduler, thread)

  install_close_hook!(scheduler)
  watchdog.scheduler_installed(thread: thread)
  self
rescue StandardError
  watchdog.scheduler_unsupported(thread: thread)
  raise unless watchdog.fail_open?

  self
end