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 +32 -15
- data/README.md +35 -0
- data/lib/dia.rb +1 -1
- data/lib/dia/sandbox.rb +62 -15
- data/test/suite/exceptions_text.rb +41 -0
- metadata +5 -3
data/NEWS.md
CHANGED
@@ -1,25 +1,36 @@
|
|
1
1
|
## NEWS
|
2
2
|
|
3
3
|
### 1.5
|
4
|
-
*
|
5
|
-
|
6
|
-
*
|
7
|
-
|
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.
|
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
|
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
|
20
|
-
|
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.
|
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
|
31
|
-
|
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
|
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
|
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
|
42
|
-
|
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
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
|
-
|
78
|
-
|
79
|
-
|
107
|
+
begin
|
108
|
+
if sandbox_init(FFI::MemoryPointer.from_string(@profile),
|
109
|
+
0x0001,
|
110
|
+
err = FFI::MemoryPointer.new(:pointer)) == -1
|
80
111
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
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
|
-
|
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-
|
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
|