| Inside the Go playground |
| |
| Francesc Campoy Flores |
| Developer Advocate, Gopher |
| @francesc |
| campoy@golang.org |
| http://campoy.cat |
| |
| * Agenda |
| |
| - What is the Go playground |
| |
| - What could go wrong |
| |
| - What did we do to avoid it |
| |
| - An animated ASCII train |
| |
| * The Go playground |
| |
| .image playground/img/play.png 500 _ |
| .caption [[/play/][go.dev/play]] |
| |
| * De facto pastebin of the Go community |
| |
| .image playground/img/share.png 500 _ |
| .caption [[/play/p/bJYnajZ6Kp][go.dev/play/p/bJYnajZ6Kp]] |
| |
| * The Go tour |
| |
| .image playground/img/tour.png 500 _ |
| .caption [[/tour/][go.dev/tour]] |
| |
| * Executable examples on documentation |
| |
| .image playground/img/examples.png 500 _ |
| .caption [[/pkg/strings/#example_Fields][go.dev/pkg/strings]] |
| |
| * Executable code on blog posts |
| |
| .image playground/img/blog.png 500 _ |
| .caption [[/blog/slices][go.dev/blog/slices]] |
| |
| * Executable slides |
| |
| .play playground/hello.go |
| |
| These slides are driven by the `present` Go tool |
| |
| go get code.google.com/go.tools/cmd/present |
| |
| * Naive implementation |
| |
| * Architecture |
| |
| .image playground/img/arch.png 500 _ |
| |
| * Backend |
| |
| Let's start with something simple |
| |
| - receive code |
| - compile it |
| - run it |
| |
| * What could go wrong? |
| |
| .image playground/img/areyousure.png 500 _ |
| |
| ########### |
| ## Issues # |
| ########### |
| |
| * Resource exhaustion |
| |
| * Exhausting memory on the stack |
| |
| `stack`overflow` |
| |
| .play playground/stack.go |
| |
| The runtime catches the error and panics. |
| |
| * Too much memory on the heap |
| |
| `out`of`memory` |
| |
| .play playground/heap.go |
| |
| Again the runtime catches the error and panics. |
| |
| * Too much CPU time |
| |
| .play playground/loop.go |
| |
| * Stealing resources by sleeping |
| |
| .play playground/sleep.go |
| |
| A sleeping program still consumes resources. |
| |
| Easy way of having a Denial of Service attack. |
| |
| * Accessing things you shouldn't |
| |
| * File system access |
| |
| User code shouldn't be able to modify the backend's file system. |
| |
| - Reading sensitive information |
| |
| - Installing backdoors |
| |
| - General mayhem |
| |
| .play playground/removeall.go /func main/,/^}/ |
| |
| * Network access |
| |
| .play playground/http.go /func main/,/^}/ |
| |
| * Use your imagination |
| |
| .image playground/img/cat.jpg 500 _ |
| |
| ################### |
| # Countermeasures # |
| ################### |
| |
| * Countermeasures |
| |
| * Restricting resource usage with ulimit |
| |
| Default limits are not safe enough. |
| |
| `ulimit` could solve this. |
| |
| -d maximum size of data segment or heap (in kbytes) |
| |
| -s maximum size of stack segment (in kbytes) |
| |
| -t maximum CPU time (in seconds) |
| |
| -v maximum size of virtual memory (in kbytes) |
| |
| * Native Client |
| |
| Originally designed to execute native code in Chrome safely. |
| |
| NaCl defines restrictions on the binaries being executed. |
| |
| The code runs in a sandbox isolated from the underlying OS. |
| |
| - No file access |
| - No network access |
| |
| .image playground/img/nacl.png 300 _ |
| |
| * Isolating process execution with NaCl |
| |
| We use NaCl to: |
| |
| - limit CPU time |
| |
| - limit memory |
| |
| - isolate from the filesystem |
| |
| - isolate from the network |
| |
| Process can only write to stdout/stderr. |
| |
| * Limiting user time |
| |
| "No sleeping in the playground." |
| |
| Custom runtime with a fake `time` package. |
| |
| func Sleep(d time.Duration) { |
| panic("No sleeping in the playground") |
| } |
| |
| * Restoring functionality |
| |
| * Faking the file system |
| |
| The `syscall` package is the only link between user code and the OS kernel. |
| |
| The playground runtime has a custom `syscall` package. |
| |
| File system operations operate on a fake in-memory file system. |
| |
| .play playground/file.go /func main/, |
| |
| * Faking the network |
| |
| All network operations also use the `syscall` package. |
| |
| The network stack is also faked in-memory. |
| |
| .play playground/net.go /func main/,/^}/ |
| |
| * Faking the network (continued) |
| |
| .play playground/net.go /func dial/,/^}/ |
| |
| ########## |
| ## TIME ## |
| ########## |
| |
| * Sleeping in the playground |
| |
| Go is about concurrency. |
| |
| We need to demonstrate concurrency in blog posts and talks. |
| |
| And demonstrating concurrency without `time` is hard. |
| |
| * What to do if an open source project lacks a feature? |
| |
| .image playground/img/gopherbw.png 500 _ |
| |
| * File a bug! |
| |
| .image playground/img/bug.png 500 _ |
| .caption [[https://code.google.com/p/go/issues/detail?id=4280][bug 4280]] |
| |
| * Normal behavior |
| |
| There's a special goroutine managing timers `T`. |
| |
| A goroutine `G` calls `time.Sleep`: |
| |
| 1. `G` adds a timer to the timer heap. |
| |
| 2. `G` puts itself to sleep. |
| |
| 3. `T` tells the OS to wake it when the next timer expires and puts itself to sleep. |
| |
| 4. When `T` is woken up it looks at the timer on the top of the heap, and wakes the corresponding goroutine. |
| |
| * Intermission: deadlocks |
| |
| .play playground/deadlock.go |
| |
| Many flavors of deadlocks. |
| |
| One common property: all goroutines are asleep. |
| |
| * New behavior |
| |
| A goroutine `G` calls `time.Sleep`: |
| |
| 1. `G` adds a timer to the timer heap. |
| |
| 2. `G` puts itself to sleep. |
| |
| 3. The scheduler detects a deadlock, checks the timer heap for pending timers. |
| |
| 4. The internal clock is advanced to the next timer expiration. |
| |
| 5. The corresponding goroutines are woken up. |
| |
| * Sleeping fast |
| |
| Faking time allows precise sleep durations. |
| |
| .play playground/sleepfast.go |
| |
| * So there's no actual sleep? |
| |
| The playground's `write` syscall inserts a timestamp before each write. |
| |
| The front end translates that into a series of "events" that the browser can play back. |
| |
| .play playground/sleep.go /func main/, |
| |
| Returns directly |
| |
| { |
| "Errors":"", |
| "Events":[ |
| {"Message":"Good night\n","Delay":0}, |
| {"Message":"Good morning\n","Delay":28800000000000} |
| ] |
| } |
| |
| * So the bug was fixed |
| |
| .image playground/img/andrew.png _ 1000 |
| .caption [[/play/p/3fv0L3-z0s][go.dev/play/p/3fv0L3-z0s]] |
| |
| * And people were happy |
| |
| .image playground/img/brad.png _ 1000 |
| .caption [[/play/p/rX_3WcpUOZ][go.dev/play/p/rX_3WcpUOZ]] |
| |
| * Very happy |
| |
| .image playground/img/jan.png _ 1000 |
| .caption [[/play/p/P-Dk0NH_vf][go.dev/play/p/P-Dk0NH_vf]] |
| |
| .image playground/img/mattn.png _ 1000 |
| .caption [[/play/p/NOycgN2i6b][go.dev/play/p/NOycgN2i6b]] |
| |
| * References |
| |
| These slides: [[/talks/2014/playground.slide]] |
| |
| More about the Go tour: |
| |
| - Inside the Go playground: [[/blog/playground][go.dev/blog/playground]] |
| |
| - The Go tour: [[/tour/][go.dev/tour]] |
| |
| More about Go on NaCl: |
| |
| - Running Go under Native Client: [[https://code.google.com/p/go-wiki/wiki/NativeClient]] |
| |
| - Go 1.3 Native Client Support: [[/s/go13nacl]] |