| 1 | |
|---|
| 2 | FREAKY FREAKY SANDBOX. |
|---|
| 3 | _______________________________________________________________________________ |
|---|
| 4 | |
|---|
| 5 | This is a hack. I know it's a hack and I'm aware that it's a hack. It's not |
|---|
| 6 | yet a tried and well-worn practice. It's not old hand, right? Not old hand. |
|---|
| 7 | |
|---|
| 8 | But it is pretty fantastic. I'm really surprised how well it works. Yeah |
|---|
| 9 | let's talk about that. |
|---|
| 10 | _______________________________________________________________________________ |
|---|
| 11 | ------------------------------------------------------------------------------- |
|---|
| 12 | |
|---|
| 13 | INSTALLING THE FREAKY FREAKY SANDBOX. |
|---|
| 14 | _______________________________________________________________________________ |
|---|
| 15 | |
|---|
| 16 | To run the freaky freaky sandbox, you need a patched Ruby 1.8.5 and the sandbox |
|---|
| 17 | extension. |
|---|
| 18 | |
|---|
| 19 | There is one patch, which adds a Thread#kill! for stopping unending sandboxes. |
|---|
| 20 | Also, the patch will manage swapping sandboxes in accord with the Ruby's |
|---|
| 21 | scheduler. Lastly, it opens up the syserr_tbl, which allows the sandbox to |
|---|
| 22 | have its own set of OS exceptions. |
|---|
| 23 | |
|---|
| 24 | See the patch/ directory of this release. |
|---|
| 25 | |
|---|
| 26 | $ cd ruby-1.8.5 |
|---|
| 27 | $ patch -p1 < ruby-1.8.5-sandbox_needs.patch |
|---|
| 28 | $ make |
|---|
| 29 | # make install |
|---|
| 30 | |
|---|
| 31 | Once Ruby is patched, come back to this directory and install the extension. |
|---|
| 32 | |
|---|
| 33 | # ruby setup.rb |
|---|
| 34 | |
|---|
| 35 | There are no gems for Sandbox. This is not without reason! Sandbox _must_ be |
|---|
| 36 | loaded before RubyGems. So it is infeasible to distribute it as a gem for now. |
|---|
| 37 | _______________________________________________________________________________ |
|---|
| 38 | ------------------------------------------------------------------------------- |
|---|
| 39 | |
|---|
| 40 | RUNNING TRUSTED CODE. |
|---|
| 41 | _______________________________________________________________________________ |
|---|
| 42 | |
|---|
| 43 | Believe it or not, FreakyFreaky is really handy for running your own apps. |
|---|
| 44 | Some examples: |
|---|
| 45 | |
|---|
| 46 | * Start small interpreters which can periodically be dumped and restarted. |
|---|
| 47 | (Long-running apps can self-upgrade!) |
|---|
| 48 | |
|---|
| 49 | * Load multiple different versions of a library. Maybe you're converting |
|---|
| 50 | an old version to a new version. |
|---|
| 51 | |
|---|
| 52 | * Run multiple Rails apps. (Rails is a classic example of a crowded namespace |
|---|
| 53 | where two apps' set of modules cannot coexist.) |
|---|
| 54 | |
|---|
| 55 | For trusted code, you want to use a plain Sandbox that let's you pass code |
|---|
| 56 | back and forth. |
|---|
| 57 | |
|---|
| 58 | s = Sandbox.new |
|---|
| 59 | |
|---|
| 60 | Creates a new symbol table and copies all the boilerplate code from the main |
|---|
| 61 | interpreter. (So be sure you haven't removed any methods from the main |
|---|
| 62 | interpreter!) |
|---|
| 63 | |
|---|
| 64 | s.eval "5 + 6" |
|---|
| 65 | #=> 11 |
|---|
| 66 | |
|---|
| 67 | Use eval to execute scripts inside the sandbox. With the plain Sandbox, |
|---|
| 68 | you'll get back the actual objects from the sandbox's world. See, it's |
|---|
| 69 | okay to share objects between trusted code. So, why not? |
|---|
| 70 | |
|---|
| 71 | s.eval %{ |
|---|
| 72 | class Book |
|---|
| 73 | attr_accessor :author, :title |
|---|
| 74 | def initialize(a, t) |
|---|
| 75 | @author, @title = a, t |
|---|
| 76 | end |
|---|
| 77 | end |
|---|
| 78 | } |
|---|
| 79 | |
|---|
| 80 | book = s.eval("book = Book.new('Stanislaw Lem', 'The Star Diaries')") |
|---|
| 81 | #=> #<Book ...> |
|---|
| 82 | |
|---|
| 83 | The Book object you get back is the same which was created in the sandbox. |
|---|
| 84 | And you can certainly access and redefine the sandboxed Book class as well. |
|---|
| 85 | |
|---|
| 86 | Book = s.eval("Book") |
|---|
| 87 | class Book |
|---|
| 88 | def year |
|---|
| 89 | 1970 |
|---|
| 90 | end |
|---|
| 91 | end |
|---|
| 92 | |
|---|
| 93 | s.eval("book.year") |
|---|
| 94 | #=> 1970 |
|---|
| 95 | |
|---|
| 96 | If you do a lot of back and forth with the sandboxes, it can be tough to keep |
|---|
| 97 | track of what classes are in the sandbox and what's in main. Especially since |
|---|
| 98 | most sandboxes start to get a bit behind method-wise. |
|---|