Module: DebugSocket

Defined in:
lib/debug_socket.rb,
lib/debug_socket/version.rb

Defined Under Namespace

Modules: Commands

Constant Summary collapse

VERSION =
"0.1.11"

Class Method Summary collapse

Class Method Details

.loggerObject



35
36
37
38
39
40
# File 'lib/debug_socket.rb', line 35

def self.logger
  return @logger if defined?(@logger)

  require "logger"
  @logger = Logger.new($stderr)
end

.logger=(logger) ⇒ Object



31
32
33
# File 'lib/debug_socket.rb', line 31

def self.logger=(logger)
  @logger = logger
end

.start(path, &block) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/debug_socket.rb', line 42

def self.start(path, &block)
  pid = Process.pid
  raise "debug socket thread already running for this process" if @thread && @pid == pid

  @pid = pid

  # make sure socket is only accessible to the process owner
  old_mask = File.umask(0o0177)

  @path = path.to_s

  server = UNIXServer.new(@path)
  @thread = Thread.new do
    errors = 0
    loop do
      socket = server.accept
      input = socket.read
      logger&.warn("debug-socket-command=#{input.inspect}")

      perform_audit(input, &block) if block
      output =
        begin
          Commands.isolated_eval(input.dup)
        # We rescue Exception here because the input could have SyntaxErrors etc.
        rescue Exception => e # rubocop:disable Lint/RescueException
          logger&.error { "debug-socket-error=#{e.inspect} input=#{input.inspect} path=#{@path} backtrace=#{e.backtrace.inspect}" }
          "#{e.class.name}: #{e.message}\n#{e.backtrace.join("\n")}"
        end
      socket.puts(output)

      errors = 0
    rescue StandardError => e
      errors += 1
      logger&.error { "debug-socket-error=#{e.inspect} errors=#{errors} path=#{@path} backtrace=#{e.backtrace.inspect}" }
      raise e if errors > 20

      sleep(1)
    ensure
      socket&.close
    end
  rescue Exception => e # rubocop:disable Lint/RescueException
    logger&.error { "debug-socket-error=#{e.inspect} DebugSocket is broken now path=#{@path} backtrace=#{e.backtrace.inspect}" }
  end

  logger&.warn { "Debug socket listening on #{@path}" }

  @thread
ensure
  File.umask(old_mask) if old_mask
end

.stopObject



93
94
95
96
97
98
99
# File 'lib/debug_socket.rb', line 93

def self.stop
  @thread&.kill
  File.unlink(@path) if @path && File.exist?(@path)
  @thread = nil
  @pid = nil
  @path = nil
end