Merge "veyron/lib/bluetooth: Remove unnecessary dependencies"
diff --git a/tools/playground/compilerd/main.go b/tools/playground/compilerd/main.go
index 82a4e11..b565ae3 100644
--- a/tools/playground/compilerd/main.go
+++ b/tools/playground/compilerd/main.go
@@ -4,8 +4,12 @@
"bytes"
"encoding/json"
"fmt"
+ "math/rand"
"net/http"
+ "os"
"os/exec"
+ "os/signal"
+ "syscall"
"time"
)
@@ -19,6 +23,19 @@
Events []Event
}
+// This channel is closed when the server begins shutting down.
+// No values are ever sent to it.
+var lameduck chan bool = make(chan bool)
+
+func healthz(w http.ResponseWriter, r *http.Request) {
+ select {
+ case <- lameduck:
+ w.WriteHeader(http.StatusInternalServerError)
+ default:
+ w.Write([]byte("OK"))
+ }
+}
+
func handler(w http.ResponseWriter, r *http.Request) {
if r.Body == nil || r.Method != "POST" {
w.WriteHeader(http.StatusBadRequest)
@@ -68,6 +85,54 @@
}
func main() {
+ limit_min := 60
+ delay_min := limit_min/2 + rand.Intn(limit_min/2)
+
+ // VMs will be periodically killed to prevent any owned vms from
+ // causing damage. We want to shutdown cleanly before then so
+ // we don't cause requests to fail.
+ go WaitForShutdown(time.Minute * time.Duration(delay_min))
+
http.HandleFunc("/compile", handler)
+ http.HandleFunc("/healthz", healthz)
http.ListenAndServe(":8181", nil)
}
+
+func WaitForShutdown(limit time.Duration) {
+ var beforeExit func() error
+
+ // Shutdown if we get a SIGTERM
+ term := make(chan os.Signal, 1)
+ signal.Notify(term, syscall.SIGTERM)
+
+ // Or if the time limit expires
+ deadline := time.After(limit)
+ fmt.Println("Shutting down at", time.Now().Add(limit))
+Loop:
+ for {
+ select {
+ case <-deadline:
+ // Shutdown the vm.
+ fmt.Println("Deadline expired, shutting down.")
+ beforeExit = exec.Command("sudo", "halt").Run
+ break Loop
+ case <-term:
+ fmt.Println("Got SIGTERM, shutting down.")
+ // VM is probably already shutting down, so just exit.
+ break Loop
+ }
+ }
+ // Fail health checks so we stop getting requests.
+ close(lameduck)
+ // Give running requests time to finish.
+ time.Sleep(30 * time.Second)
+
+ // Then go ahead and shutdown.
+ if beforeExit != nil {
+ err := beforeExit()
+ if err != nil {
+ panic(err)
+ }
+ }
+ os.Exit(0)
+}