Class: Krill::ProtocolSandbox

Inherits:
Object
  • Object
show all
Defined in:
lib/krill/protocol_sandbox.rb

Overview

Defines an execution environment for the protocol of a job. Loads the protocol into a unique namespace module, and extends the class with protocol base methods.

Despite the name, this is not yet a sandbox, so protocols may still do bad, bad things to the server environment.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(job:, debug: false, mutex: nil, thread_status: nil) ⇒ ProtocolSandbox

Initializes a new Krill::ProtocolSandbox object.

Parameters:

  • job (Job)

    the job

  • debug (TrueClass, FalseClass)

    whether protocol runs in debug mode

  • mutex (Mutex)

    lock object for synchronization (nil)

  • thread_status (ThreadStatus)

    status for manager thread (nil)

Raises:



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/krill/protocol_sandbox.rb', line 27

def initialize(job:, debug: false, mutex: nil, thread_status: nil)
  @job = job
  operation_type = @job.operation_type
  base_class_prefix = 'KrillProtocolBase'
  namespace_prefix = 'ExecutionNamespace'
  suffix = generate_suffix(length: 32, prefix: base_class_prefix)
  base_class_name = "#{base_class_prefix}#{suffix}"
  base_class = make_base(
    name: base_class_name,
    debug: debug,
    mutex: mutex,
    thread_status: thread_status
  )
  @namespace_name = "#{namespace_prefix}#{suffix}"
  namespace = Krill.make_namespace(name: @namespace_name)
  namespace.add(code: operation_type.protocol)
  namespace::Protocol.include(base_class)
  @protocol = namespace::Protocol.new
rescue SyntaxError => e
  raise KrillSyntaxError.new(operation_type: operation_type, error: e)
rescue StandardError, NoMemoryError, ScriptError, SecurityError, SystemExit, SystemStackError => e
  raise KrillError.new(job: job, error: e, namespace: @namespace_name)
end

Instance Attribute Details

#jobObject (readonly)

these are here for observability in tests



14
15
16
# File 'lib/krill/protocol_sandbox.rb', line 14

def job
  @job
end

#protocolObject (readonly)

these are here for observability in tests



14
15
16
# File 'lib/krill/protocol_sandbox.rb', line 14

def protocol
  @protocol
end

Instance Method Details

#done?TrueClass, FalseClass

Indicates whether the job has completed.

Returns:

  • (TrueClass, FalseClass)

    true if the job is complete, otherwise false



88
89
90
# File 'lib/krill/protocol_sandbox.rb', line 88

def done?
  @job.done?
end

#executeObject

Executes protocol.main for the job.

Captures the return value, and the following exceptions:

  • NoMemoryError occurs if allocation exceeds allowed storage (e.g., string larger than max capacity)
  • ScriptError
  • SecurityError
  • StandardError
  • SystemExit
  • SystemStackError

Raises:

  • (KrillError)

    if one of the exceptions above is caught



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/krill/protocol_sandbox.rb', line 62

def execute
  @job.start
  begin
    return_value = @protocol.main
    @job.reload
    @job.append_step(operation: 'complete', rval: return_value)
    @job.stop('done')
  rescue StandardError, NoMemoryError, ScriptError, SecurityError, SystemExit, SystemStackError => e
    puts "#{@job.id}: EXCEPTION #{e}"
    puts e.backtrace[0, 10]
    @job.reload
    @job.stop('error')
    @job.append_step(operation: 'error', message: e.to_s, backtrace: e.backtrace[0, 10])
    @job.append_step(operation: 'next', time: Time.zone.now, inputs: {})
    @job.append_step(operation: 'aborted', rval: {})
    raise e if e.is_a?(ProtocolError)

    raise KrillError.new(job: @job, error: e, namespace: @namespace_name)
  ensure
    @job.save
  end
end