dia 1.5.pre → 1.5.pre.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/NEWS.md CHANGED
@@ -1,25 +1,36 @@
1
1
  ## NEWS
2
2
 
3
3
  ### 1.5
4
- * Dia::Sandbox#running?, Dia::Sandbox#exit_status, and Dia::Sandbox#terminate will return nil if you call them before
5
- calling Dia::Sandbox#run().
6
- * Added Dia::Sandbox#exit_status for collecting the exit status of a child process running under a sandbox.
7
- * Dia::Sandbox#run was not returning the PID of the process running under a sandbox like told in the documentation - it is now.
4
+ * Added Dia::Sandbox#exception() for inspecting an exception raised in a sandbox
5
+ from the parent process.
6
+ * Fixed a small bug introduced in 1.5.pre - a typo, only encountered if
7
+ Dia::SandboxException was raised.
8
+ * Dia::Sandbox#running?, Dia::Sandbox#exit_status, and Dia::Sandbox#terminate
9
+ will return nil if you call them before calling Dia::Sandbox#run().
10
+ * Added Dia::Sandbox#exit_status for collecting the exit status of a child
11
+ process running under a sandbox.
12
+ * Dia::Sandbox#run was not returning the PID of the process running under a
13
+ sandbox like told in the documentation - it is now.
8
14
 
9
15
  ### 1.4
10
- * A typo broke support for launching applications in a sandbox. (Bug affects 1.3 and all the 1.4 *pre* releases)
16
+ * A typo broke support for launching applications in a sandbox.
17
+ (Bug affects 1.3 and all the 1.4 *pre* releases)
11
18
  * Mac OSX 10.5 reported as working! (Bug fix)
12
19
  Many thanks to Josh Creek for reporting and helping me debug this bug.
13
20
  * Use ffi\_lib() to explicitly load the dynamic library "sandbox", or "System"
14
21
  * Depend explicitly on FFI v0.6.2
15
- * Dia::Sandbox#run accepts a variable amount of arguments that will be passed onto the block supplied to the constructer.
22
+ * Dia::Sandbox#run accepts a variable amount of arguments that will be passed
23
+ onto the block supplied to the constructer.
16
24
  * Added "test/\*\*/*.rb" to the gem specification as test files..
17
25
 
18
26
  ### 1.3
19
- * Added Dia::Sandbox#running? to check if a process running a sandbox is alive or not.
20
- * Dia::Sandbox only exposes its instance variables through getters now. No more setters.
27
+ * Added Dia::Sandbox#running? to check if a process running a sandbox is alive
28
+ or not.
29
+ * Dia::Sandbox only exposes its instance variables through getters now.
30
+ No more setters.
21
31
  * Dia::Sandbox#app_path is now Dia::Sandbox#app
22
- * Removed run\_with\_block in favor of passing a block to the constructer. Dia::Sandbox#run is used to execute a block or an application now,
32
+ * Removed run\_with\_block in favor of passing a block to the constructer.
33
+ Dia::Sandbox#run is used to execute a block or an application now,
23
34
  but only one or the other may be supplied to the constructer.
24
35
  * Removed Dia::SandBox in favor of Dia::Sandbox.
25
36
  * Added "has_rdoc = 'yard'" to the gem spec.
@@ -27,19 +38,25 @@
27
38
  * SandBoxException becomes SandboxException.
28
39
 
29
40
  ### 1.2
30
- * I've decided to use Dia::Sandbox instead of Dia::SandBox but it won't be removed until 1.3 .. (Deprecated for 1.2)
31
- * I've decided to remove the explicit exit() call in a sandbox spawned with run\_with\_block .. (Introduced in 1.1 Final)
41
+ * I've decided to use Dia::Sandbox instead of Dia::SandBox but it won't
42
+ be removed until 1.3 .. (Deprecated for 1.2)
43
+ * I've decided to remove the explicit exit() call in a sandbox spawned with
44
+ run\_with\_block .. (Introduced in 1.1 Final)
32
45
  * Added Dia::Sandbox#terminate for terminating a sandbox.
33
- * Process.detach(*sandbox pid*) is used in the parent process that spawns a sandbox to avoid collecting zombies ..
46
+ * Process.detach(*sandbox pid*) is used in the parent process that spawns a
47
+ sandbox to avoid collecting zombies ..
34
48
 
35
49
  ### 1.1 (final)
36
- * Dia::SandBox#run\_with\_block will exit the child process spawned by itself incase the user forgets to ..
50
+ * Dia::SandBox#run\_with\_block will exit the child process spawned by itself
51
+ incase the user forgets to ..
37
52
  * Added some tests for Dia::Sandbox.new#run\_with\_block ..
38
53
  We ain't got full coverage but we're getting there.
39
54
  * A person reported that ffi 0.6.0 does not work with dia ..
40
55
  Supplied an explicit dependency on ffi 0.5.4 until I figure it out.
41
- * You can run a block of ruby under a sandbox now but I had to change the order of arguments in the constructer ..
42
- First argument is the profile, and (optionally) the second is the application path.
56
+ * You can run a block of ruby under a sandbox now but I had to change the order
57
+ of arguments in the constructer ..
58
+ First argument is the profile, and (optionally) the second is the application
59
+ path.
43
60
  If you're running a block of ruby, you can forget about the second.
44
61
  * I documented my methods!
45
62
 
data/README.md CHANGED
@@ -86,6 +86,41 @@ If you need to check if a sandbox you have spawned is still running, you can use
86
86
  puts sandbox.running? # => true
87
87
 
88
88
 
89
+ **Collecting the exit status of a sandbox**
90
+
91
+ The sandbox environment is run in a child process, and you can collect its
92
+ exit status through the #exit_status() method. This method is only available
93
+ from 0.5.pre onwards.
94
+
95
+ require 'rubygems'
96
+ require 'dia'
97
+ sandbox = Dia::Sandbox.new(Dia::Profiles::NO_OS_SERVICES) do
98
+ exit(10)
99
+ end
100
+
101
+ sandbox.run()
102
+ sandbox.exit_status() # => 10
103
+
104
+ **Accessing an exception raised in a sandbox**
105
+
106
+ Since 1.5, an exception raised in a sandbox can be accessed from the parent
107
+ process. This only works as long as you don't try to capture the exception
108
+ raised in a block by yourself or if you do, you re-raise the exception after
109
+ capturing it so Dia can forward the exception to the parent process.
110
+
111
+ require 'rubygems'
112
+ require 'dia'
113
+ sandbox = Dia::Sandbox.new(Dia::Profiles::NO_OS_SERVICES) do
114
+ raise()
115
+ end
116
+
117
+ sandbox.run()
118
+ sleep(0.1) # Let the parent receive the exception.
119
+ # Only neccesary for scenarios where an exception is raised
120
+ # rather quickly.
121
+
122
+ puts sandbox.exception().class # prints "RuntimeError"
123
+
89
124
  .. Please see the yardoc [documentation](http://yardoc.org/docs/robgleeson-Dia) for more in-depth coverage of these methods,
90
125
  in particular the documentation for the `Dia::Sandbox` class.
91
126
 
data/lib/dia.rb CHANGED
@@ -5,7 +5,7 @@ require File.join(File.dirname(__FILE__), 'dia/commonapi.rb')
5
5
  require File.join(File.dirname(__FILE__), 'dia/sandbox.rb')
6
6
 
7
7
  module Dia
8
- VERSION = '1.5.pre'
8
+ VERSION = '1.5.pre.2'
9
9
  class SandboxException < StandardError; end
10
10
  end
11
11
 
data/lib/dia/sandbox.rb CHANGED
@@ -2,13 +2,15 @@ module Dia
2
2
 
3
3
  class Sandbox
4
4
 
5
+ require('io/wait')
6
+
5
7
  include Dia::CommonAPI
6
8
 
7
9
  attr_reader :app
8
10
  attr_reader :profile
9
11
  attr_reader :pid
10
12
  attr_reader :blk
11
-
13
+
12
14
  # The constructer accepts a profile as the first parameter, and an
13
15
  # application path _or_ block as its second parameter.
14
16
  #
@@ -48,8 +50,35 @@ module Dia
48
50
  @blk = blk
49
51
  @profile = profile
50
52
  @pid = nil
53
+ initialize_streams()
51
54
  end
52
-
55
+
56
+ # The exception() method returns an instance or subclass instance of
57
+ # Exception which has been raised in a sandbox.
58
+ #
59
+ # This method can be used if you need access(from the parent process)
60
+ # to an exception raised in your sandbox.
61
+ #
62
+ # If the sandbox raises an exception rather quickly, you might need to
63
+ # sleep(X) (0.3-0.5s on my machine) before the parent process
64
+ # recieves the exception.
65
+ #
66
+ # @return [Exception, nil] Returns an instance or subclass instance of
67
+ # Exception when successful, and nil when
68
+ # there is no exception available.
69
+ # @since 1.5
70
+ def exception()
71
+ @write.close()
72
+ if @read.ready?()
73
+ ret = Marshal.load(@read.gets())
74
+ else
75
+ ret = nil
76
+ end
77
+ @read.close()
78
+ initialize_streams()
79
+ ret
80
+ end
81
+
53
82
  # The run method will spawn a child process and run the application _or_
54
83
  # block supplied to the constructer under a sandbox.
55
84
  # This method will not block.
@@ -73,22 +102,33 @@ module Dia
73
102
  # @return [Fixnum] The Process ID(PID) that the sandboxed
74
103
  # application is being run under.
75
104
  def run(*args)
105
+ initialize_streams()
76
106
  @pid = fork do
77
- if sandbox_init(FFI::MemoryPointer.from_string(@profile),
78
- 0x0001,
79
- err = FFI::MemoryPointer.new(:pointer)) == -1
107
+ begin
108
+ if sandbox_init(FFI::MemoryPointer.from_string(@profile),
109
+ 0x0001,
110
+ err = FFI::MemoryPointer.new(:pointer)) == -1
80
111
 
81
- raise(Dia::SandboxException, "Failed to initialize sandbox" /
82
- "(#{err.read_pointer.read_string})")
83
- end
84
-
85
- if @app
86
- exec(@app)
87
- else
88
- @blk.call(*args)
112
+ raise(Dia::SandboxException, "Failed to initialize sandbox" \
113
+ "(#{err.read_pointer.read_string})")
114
+ end
115
+
116
+ if @app
117
+ exec(@app)
118
+ else
119
+ @blk.call(*args)
120
+ end
121
+
122
+ rescue SystemExit, Interrupt => e
123
+ raise(e)
124
+ rescue Exception => e
125
+ @write.write(Marshal.dump(e))
126
+ ensure
127
+ @write.close()
128
+ @read.close()
89
129
  end
90
130
  end
91
-
131
+
92
132
  # parent ..
93
133
  @thr = Process.detach(@pid)
94
134
  @pid
@@ -102,7 +142,8 @@ module Dia
102
142
  # under a sandbox.
103
143
  # Returns nil if Dia::Sandbox#run has not
104
144
  # been called yet, or if the process stopped
105
- # abnormally(ie: through SIGKILL, or #terminate).
145
+ # abnormally(ie: through SIGKILL, or #terminate).
146
+ # @since 1.5
106
147
  def exit_status()
107
148
  @thr.value().exitstatus() unless @thr.nil?
108
149
  end
@@ -143,7 +184,13 @@ module Dia
143
184
  end
144
185
  end
145
186
  end
187
+
188
+ private
146
189
 
190
+ def initialize_streams()
191
+ @read, @write = IO.pipe()
192
+ end
193
+
147
194
  end
148
195
 
149
196
  end
@@ -0,0 +1,41 @@
1
+ BareTest.suite('Exceptions', :tags => [ :exception ]) do
2
+ assert('Dia::SandboxException is raised if a call to sandbox_init() fails') do
3
+ sandbox = Dia::Sandbox.new(Dia::Profiles::NO_OS_SERVICES) do
4
+ # ...
5
+ end
6
+ sandbox.instance_variable_set("@profile", "i am going to break")
7
+ sandbox.run
8
+ sleep(0.1)
9
+ equal(Dia::SandboxException, sandbox.exception().class)
10
+ end
11
+
12
+ assert('Dia::Sandbox#exception() will return an exception raised in the sandbox') do
13
+ sandbox = Dia::Sandbox.new(Dia::Profiles::NO_OS_SERVICES) do
14
+ raise()
15
+ end
16
+
17
+ sandbox.run()
18
+ sleep(0.1)
19
+ equal(RuntimeError, sandbox.exception.class())
20
+ end
21
+
22
+ assert('Dia::Sandbox#exception() returns nil if called before ' \
23
+ 'Dia::Sandbox#run()') do
24
+ sandbox = Dia::Sandbox.new(Dia::Profiles::NO_OS_SERVICES) do
25
+ # ...
26
+ end
27
+ equal(nil, sandbox.exception())
28
+ end
29
+
30
+ assert('Dia::Sandbox#exception() returns nil after a second call') do
31
+ sandbox = Dia::Sandbox.new(Dia::Profiles::NO_OS_SERVICES) do
32
+ raise()
33
+ end
34
+
35
+ sandbox.run()
36
+ sleep(0.1)
37
+ equal(RuntimeError, sandbox.exception().class)
38
+ equal(nil, sandbox.exception())
39
+ end
40
+
41
+ end
metadata CHANGED
@@ -6,7 +6,8 @@ version: !ruby/object:Gem::Version
6
6
  - 1
7
7
  - 5
8
8
  - pre
9
- version: 1.5.pre
9
+ - 2
10
+ version: 1.5.pre.2
10
11
  platform: ruby
11
12
  authors:
12
13
  - Robert Gleeson
@@ -14,7 +15,7 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-05-03 00:00:00 +01:00
18
+ date: 2010-05-07 00:00:00 +01:00
18
19
  default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
@@ -83,7 +84,7 @@ has_rdoc: yard
83
84
  homepage:
84
85
  licenses: []
85
86
 
86
- post_install_message: " ********************************************************************\n Dia (1.5.pre)\n \n Thanks for installing Dia, 1.5.pre! \n \n Keep up with the latest @ GitHub:\n http://github.com/robgleeson/dia\n ********************************************************************\n"
87
+ post_install_message: " ********************************************************************\n Dia (1.5.pre.2)\n \n Thanks for installing Dia, 1.5.pre.2! \n \n Keep up with the latest @ GitHub:\n http://github.com/robgleeson/dia\n ********************************************************************\n"
87
88
  rdoc_options: []
88
89
 
89
90
  require_paths:
@@ -114,6 +115,7 @@ summary: Dia allows you to sandbox application(s) or block(s) of rubyon the OSX
114
115
  test_files:
115
116
  - test/setup.rb
116
117
  - test/suite/check_if_sandbox_is_alive_test.rb
118
+ - test/suite/exceptions_text.rb
117
119
  - test/suite/exit_status_test.rb
118
120
  - test/suite/passing_parameters_to_constructer_test.rb
119
121
  - test/suite/run_block_in_sandbox_test.rb