dia 1.5.pre → 1.5.pre.2

Sign up to get free protection for your applications and to get access to all the features.
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