func TrapKillSignals() {
	c := make(chan os.Signal, 1)
	signal.Notify(c, syscall.SIGINT)
	signal.Notify(c, syscall.SIGTERM)
	signal.Notify(c, syscall.SIGKILL)
	go func() {
		for range c {
			log.Println("Caught a fatal signal. Terminating.")
			app.CallExitFuncs()
			os.Exit(1)
		}
	}()
}
func main() {
	flag.Parse()

	// Make sure exit functions get called. This program has no normal exit -- it either dies from panics
	// or from catching fatal signals. The former case is handled by defer. The latter case is handled
	// by TrapKillSignals.
	defer app.CallExitFuncs()
	TrapKillSignals()

	if !*stderr {
		// Set up log file.
		logname := path.Join(os.Getenv("HOME"), "server.log")
		err := os.Rename(logname, fmt.Sprintf(
			"%s.%s.%d", logname, time.Now().Format("2006-01-02"), time.Now().Unix()))
		if err != nil && !os.IsNotExist(err) {
			log.Fatalln(err)
		}
		logfile, err := os.Create(logname)
		checkInitError(err)
		app.RunAtExit(func() { logfile.Close() })
		log.Println("Subsequent log messages will go to disk, not stderr.")
		log.SetOutput(logfile)
	} else {
		log.Println("Logging to stderr.")
	}
	log.Println("Starting server.")

	// Static files.
	pwd, err := os.Getwd()
	checkInitError(err)
	http.Handle("/", http.FileServer(http.Dir(path.Join(pwd, "static-files"))))

	// Special handler for static graphs.
	http.Handle("/graph/", http.StripPrefix("/graph/", http.FileServer(http.Dir(app.TempGraphDir))))

	// Visualization builder.
	http.HandleFunc("/visualize", visualizeHandler)

	// Loading page.
	template.Must(template.ParseFiles("templates/loading.html")) // Sanity check.
	http.HandleFunc("/loading", loadingHandler)

	// Dashboard page.
	template.Must(template.ParseFiles("templates/dashboard.html")) // Sanity check.
	http.HandleFunc("/dashboard", dashboardHandler)

	// Contact info signup.
	smtpPassword = os.Getenv("EMAIL_CHARTS_SMTP_PASSWORD")
	if smtpPassword == "" {
		log.Println("Must set EMAIL_CHARTS_SMTP_PASSWORD")
		return
	}
	http.HandleFunc("/staytuned", signupHandler)
	ok := func(w http.ResponseWriter, _ *http.Request) {
		w.Write([]byte("ok"))
	}
	http.HandleFunc("/_ah/start", ok)
	http.HandleFunc("/_ah/health", ok)

	log.Printf(http.ListenAndServe(*httpAddr, Log(http.DefaultServeMux)).Error())
}