make an error handling function
Signed-off-by: Jeff Carr <jcarr@wit.com>
This commit is contained in:
parent
e1b30b97cc
commit
fc6db10c22
|
@ -0,0 +1,33 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var start time.Time
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
start = time.Now()
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("main() started", time.Since(start))
|
||||||
|
chan1 := make(chan string, 2)
|
||||||
|
chan2 := make(chan string, 2)
|
||||||
|
|
||||||
|
chan1 <- "Value 1"
|
||||||
|
chan1 <- "Value 2"
|
||||||
|
chan2 <- "Value 1"
|
||||||
|
chan2 <- "Value 2"
|
||||||
|
|
||||||
|
select {
|
||||||
|
case res := <-chan1:
|
||||||
|
fmt.Println("Response from chan1", res, time.Since(start))
|
||||||
|
case res := <-chan2:
|
||||||
|
fmt.Println("Response from chan2", res, time.Since(start))
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("main() stopped", time.Since(start))
|
||||||
|
for {}
|
||||||
|
}
|
|
@ -0,0 +1,115 @@
|
||||||
|
// In the previous example we used explicit locking with
|
||||||
|
// [mutexes](mutexes) to synchronize access to shared state
|
||||||
|
// across multiple goroutines. Another option is to use the
|
||||||
|
// built-in synchronization features of goroutines and
|
||||||
|
// channels to achieve the same result. This channel-based
|
||||||
|
// approach aligns with Go's ideas of sharing memory by
|
||||||
|
// communicating and having each piece of data owned
|
||||||
|
// by exactly 1 goroutine.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// In this example our state will be owned by a single
|
||||||
|
// goroutine. This will guarantee that the data is never
|
||||||
|
// corrupted with concurrent access. In order to read or
|
||||||
|
// write that state, other goroutines will send messages
|
||||||
|
// to the owning goroutine and receive corresponding
|
||||||
|
// replies. These `readOp` and `writeOp` `struct`s
|
||||||
|
// encapsulate those requests and a way for the owning
|
||||||
|
// goroutine to respond.
|
||||||
|
type readOp struct {
|
||||||
|
key int
|
||||||
|
resp chan int
|
||||||
|
}
|
||||||
|
type writeOp struct {
|
||||||
|
key int
|
||||||
|
val int
|
||||||
|
resp chan bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
// As before we'll count how many operations we perform.
|
||||||
|
var readOps uint64
|
||||||
|
var writeOps uint64
|
||||||
|
|
||||||
|
// The `reads` and `writes` channels will be used by
|
||||||
|
// other goroutines to issue read and write requests,
|
||||||
|
// respectively.
|
||||||
|
reads := make(chan readOp)
|
||||||
|
writes := make(chan writeOp)
|
||||||
|
|
||||||
|
// Here is the goroutine that owns the `state`, which
|
||||||
|
// is a map as in the previous example but now private
|
||||||
|
// to the stateful goroutine. This goroutine repeatedly
|
||||||
|
// selects on the `reads` and `writes` channels,
|
||||||
|
// responding to requests as they arrive. A response
|
||||||
|
// is executed by first performing the requested
|
||||||
|
// operation and then sending a value on the response
|
||||||
|
// channel `resp` to indicate success (and the desired
|
||||||
|
// value in the case of `reads`).
|
||||||
|
go func() {
|
||||||
|
var state = make(map[int]int)
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case read := <-reads:
|
||||||
|
read.resp <- state[read.key]
|
||||||
|
case write := <-writes:
|
||||||
|
state[write.key] = write.val
|
||||||
|
write.resp <- true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// This starts 100 goroutines to issue reads to the
|
||||||
|
// state-owning goroutine via the `reads` channel.
|
||||||
|
// Each read requires constructing a `readOp`, sending
|
||||||
|
// it over the `reads` channel, and the receiving the
|
||||||
|
// result over the provided `resp` channel.
|
||||||
|
for r := 0; r < 100; r++ {
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
read := readOp{
|
||||||
|
key: rand.Intn(5),
|
||||||
|
resp: make(chan int)}
|
||||||
|
reads <- read
|
||||||
|
<-read.resp
|
||||||
|
atomic.AddUint64(&readOps, 1)
|
||||||
|
time.Sleep(time.Millisecond)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// We start 10 writes as well, using a similar
|
||||||
|
// approach.
|
||||||
|
for w := 0; w < 10; w++ {
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
write := writeOp{
|
||||||
|
key: rand.Intn(5),
|
||||||
|
val: rand.Intn(100),
|
||||||
|
resp: make(chan bool)}
|
||||||
|
writes <- write
|
||||||
|
<-write.resp
|
||||||
|
atomic.AddUint64(&writeOps, 1)
|
||||||
|
time.Sleep(time.Millisecond)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let the goroutines work for a second.
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
|
||||||
|
// Finally, capture and report the op counts.
|
||||||
|
readOpsFinal := atomic.LoadUint64(&readOps)
|
||||||
|
fmt.Println("readOps:", readOpsFinal)
|
||||||
|
writeOpsFinal := atomic.LoadUint64(&writeOps)
|
||||||
|
fmt.Println("writeOps:", writeOpsFinal)
|
||||||
|
}
|
|
@ -1,5 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
|
// This should build and upload the binary to mirrors
|
||||||
|
|
||||||
import "log"
|
import "log"
|
||||||
// import "fmt"
|
// import "fmt"
|
||||||
import "os"
|
import "os"
|
||||||
|
@ -20,7 +22,22 @@ var builddir string
|
||||||
var homedir string
|
var homedir string
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
os.Chdir("~/go/src/wit/cloud-control-panel")
|
// os.Chdir("~/go/src/wit/cloud-control-panel")
|
||||||
|
|
||||||
|
// set epoch, version,
|
||||||
|
// set build cloud-control-panel
|
||||||
|
|
||||||
|
// get build time
|
||||||
|
// go build -ldflags
|
||||||
|
// "
|
||||||
|
// -X main.GITCOMMIT=${GITCOMMIT}
|
||||||
|
// -X main.GOVERSION='${GOVERSION}'
|
||||||
|
// -X main.BUILDTIME='${BUILDTIME}'
|
||||||
|
// -X main.VERSION=${VERSION}
|
||||||
|
// "
|
||||||
|
|
||||||
|
// upload binary to mirrors.wit.com/cloud/control-panel
|
||||||
|
|
||||||
|
|
||||||
setupUser()
|
setupUser()
|
||||||
|
|
||||||
|
@ -36,39 +53,13 @@ func main() {
|
||||||
shell.Run("pwd")
|
shell.Run("pwd")
|
||||||
|
|
||||||
for {
|
for {
|
||||||
time.Sleep(time.Second * 5)
|
|
||||||
build()
|
build()
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
|
time.Sleep(time.Second * 5)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
// slow down the polling to every 2 seconds
|
|
||||||
shell.SetDelayInMsec(2000)
|
|
||||||
shell.Run("ping -c 6 localhost")
|
|
||||||
|
|
||||||
// capture ping output into a file
|
|
||||||
fout, _ := os.Create("/tmp/example1.ping.stdout")
|
|
||||||
ferr, _ := os.Create("/tmp/example1.ping.stderr")
|
|
||||||
shell.SetStdout(fout)
|
|
||||||
shell.SetStderr(ferr)
|
|
||||||
|
|
||||||
shell.Run("ping -c 5 localhost")
|
|
||||||
|
|
||||||
// turn out process exit debugging
|
|
||||||
shell.SpewOn()
|
|
||||||
|
|
||||||
fout, _ = os.Create("/tmp/example1.fail.stdout")
|
|
||||||
ferr, _ = os.Create("/tmp/example1.fail.stderr")
|
|
||||||
shell.SetStdout(fout)
|
|
||||||
shell.SetStderr(ferr)
|
|
||||||
|
|
||||||
// TODO: this might not be working
|
|
||||||
// check error handling
|
|
||||||
shell.Run("ls /tmpthisisnothere")
|
|
||||||
*/
|
|
||||||
|
|
||||||
func build() {
|
func build() {
|
||||||
// shell.SetDelayInMsec(50)
|
// shell.SetDelayInMsec(50)
|
||||||
shell.Run("go get -v .")
|
shell.Run("go get -v .")
|
||||||
|
@ -91,7 +82,6 @@ func ping() {
|
||||||
shell.Run("ping -c 6 localhost")
|
shell.Run("ping -c 6 localhost")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// func setupUser() string, string, string {
|
// func setupUser() string, string, string {
|
||||||
func setupUser() {
|
func setupUser() {
|
||||||
// look up the user information
|
// look up the user information
|
||||||
|
|
29
config.go
29
config.go
|
@ -16,10 +16,12 @@ import "os/user"
|
||||||
import "flag"
|
import "flag"
|
||||||
import "fmt"
|
import "fmt"
|
||||||
import "runtime"
|
import "runtime"
|
||||||
|
// import "runtime/debug"
|
||||||
import "io/ioutil"
|
import "io/ioutil"
|
||||||
import "strings"
|
import "strings"
|
||||||
import "reflect"
|
import "reflect"
|
||||||
import "bytes"
|
import "bytes"
|
||||||
|
// import "sys"
|
||||||
|
|
||||||
import "github.com/golang/protobuf/jsonpb"
|
import "github.com/golang/protobuf/jsonpb"
|
||||||
import pb "git.wit.com/wit/witProtobuf"
|
import pb "git.wit.com/wit/witProtobuf"
|
||||||
|
@ -271,6 +273,33 @@ func parseConfig() {
|
||||||
log.Println("config.Gitref =", config.Gitref)
|
log.Println("config.Gitref =", config.Gitref)
|
||||||
log.Println("config.Goversion =", config.Goversion)
|
log.Println("config.Goversion =", config.Goversion)
|
||||||
log.Println("config.Dirty =", config.Dirty)
|
log.Println("config.Dirty =", config.Dirty)
|
||||||
|
|
||||||
|
log.Println("runtime.Version =", runtime.Version())
|
||||||
|
log.Println("runtime Number of CPUs =", runtime.NumCPU())
|
||||||
|
log.Println("runtime Number of GoRoutines =", runtime.NumGoroutine())
|
||||||
|
|
||||||
|
log.Println("runtime.GOARCH =", runtime.GOARCH)
|
||||||
|
|
||||||
|
stackSlice := make([]byte, 12512)
|
||||||
|
s := runtime.Stack(stackSlice, false)
|
||||||
|
fmt.Printf("\n%s", stackSlice[0:s])
|
||||||
|
// blah := runtime.Stack()
|
||||||
|
spew.Dump(s)
|
||||||
|
|
||||||
|
// bi, biok := debug.ReadBuildInfo()
|
||||||
|
// log.Println("debug.BuildInfo() ok =", biok)
|
||||||
|
// spew.Dump(bi.Path)
|
||||||
|
// spew.Dump(bi.Main)
|
||||||
|
// log.Println("debug.BuildInfo.Path =", bi.Path)
|
||||||
|
|
||||||
|
errChan <- "hello"
|
||||||
|
errChan <- "hello"
|
||||||
|
errChan <- "hello"
|
||||||
|
errChan <- fmt.Errorf("mainMouseClick() got b = nil")
|
||||||
|
errChan <- "hello"
|
||||||
|
|
||||||
|
// for {}
|
||||||
|
// os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func chompBytesBuffer(buf *bytes.Buffer) string {
|
func chompBytesBuffer(buf *bytes.Buffer) string {
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
// run this and then hit:
|
||||||
|
// http://localhost:6060/debug/pprof/
|
||||||
|
//
|
||||||
|
// Also run from the command line:
|
||||||
|
// go tool pprof 'localhost:6060/debug/pprof/wit_pprof_experiment_thing?debug=1'
|
||||||
|
//
|
||||||
|
// https://medium.com/@cep21/creating-custom-go-profiles-with-pprof-b737dfc58e11
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
import "log"
|
||||||
|
import "net/http"
|
||||||
|
import _ "net/http/pprof" // the _ means only the init() is needed
|
||||||
|
import "os"
|
||||||
|
import "runtime/pprof"
|
||||||
|
import "sync/atomic"
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
var libProfile *pprof.Profile
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
profName := "wit_pprof_experiment_thing" // this ends up in the URL
|
||||||
|
libProfile = pprof.Lookup(profName)
|
||||||
|
if libProfile == nil {
|
||||||
|
libProfile = pprof.NewProfile(profName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type someResource struct {
|
||||||
|
*os.File
|
||||||
|
}
|
||||||
|
|
||||||
|
var fileIndex = int64(0)
|
||||||
|
|
||||||
|
func MustResource() *someResource {
|
||||||
|
f, err := os.Create(fmt.Sprintf("/tmp/%d.txt", atomic.AddInt64(&fileIndex, 1)))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
r := &someResource{f}
|
||||||
|
libProfile.Add(r, 1)
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *someResource) Close() error {
|
||||||
|
libProfile.Remove(r)
|
||||||
|
return r.File.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func trackAFunction() {
|
||||||
|
tracked := new(byte)
|
||||||
|
libProfile.Add(tracked, 1)
|
||||||
|
defer libProfile.Remove(tracked)
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
|
|
||||||
|
func usesAResource() {
|
||||||
|
res := MustResource()
|
||||||
|
defer res.Close()
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
http.HandleFunc("/nonblock", func(rw http.ResponseWriter, req *http.Request) {
|
||||||
|
go usesAResource()
|
||||||
|
})
|
||||||
|
http.HandleFunc("/functiontrack", func(rw http.ResponseWriter, req *http.Request) {
|
||||||
|
trackAFunction()
|
||||||
|
})
|
||||||
|
http.HandleFunc("/block", func(rw http.ResponseWriter, req *http.Request) {
|
||||||
|
usesAResource()
|
||||||
|
})
|
||||||
|
log.Println("Running!")
|
||||||
|
log.Println(http.ListenAndServe("localhost:6060", nil))
|
||||||
|
}
|
Binary file not shown.
48
main.go
48
main.go
|
@ -3,7 +3,9 @@ package main
|
||||||
import "log"
|
import "log"
|
||||||
import "os"
|
import "os"
|
||||||
import "time"
|
import "time"
|
||||||
// import "reflect"
|
import "reflect"
|
||||||
|
import "os/signal"
|
||||||
|
import "syscall"
|
||||||
|
|
||||||
// this is the king of dns libraries
|
// this is the king of dns libraries
|
||||||
import "github.com/miekg/dns"
|
import "github.com/miekg/dns"
|
||||||
|
@ -11,6 +13,7 @@ import "github.com/miekg/dns"
|
||||||
import "git.wit.com/wit/gui"
|
import "git.wit.com/wit/gui"
|
||||||
import pb "git.wit.com/wit/witProtobuf"
|
import pb "git.wit.com/wit/witProtobuf"
|
||||||
import "git.wit.com/jcarr/dnssecsocket"
|
import "git.wit.com/jcarr/dnssecsocket"
|
||||||
|
import "git.wit.com/wit/shell"
|
||||||
|
|
||||||
import "github.com/gobuffalo/packr"
|
import "github.com/gobuffalo/packr"
|
||||||
import "github.com/davecgh/go-spew/spew"
|
import "github.com/davecgh/go-spew/spew"
|
||||||
|
@ -21,6 +24,8 @@ var BUILDTIME string // this is passed in as an ldflag
|
||||||
var VERSION string // this is passed in as an ldflag
|
var VERSION string // this is passed in as an ldflag
|
||||||
|
|
||||||
var State string // used as a State machine
|
var State string // used as a State machine
|
||||||
|
var sigChan chan os.Signal
|
||||||
|
var errChan chan interface{}
|
||||||
|
|
||||||
type myButtonInfo struct {
|
type myButtonInfo struct {
|
||||||
Account *pb.Account // associated with what account?
|
Account *pb.Account // associated with what account?
|
||||||
|
@ -57,6 +62,9 @@ type myButtonInfo struct {
|
||||||
// i18n with 'po' file support
|
// i18n with 'po' file support
|
||||||
// https://github.com/leonelquinteros/gotext
|
// https://github.com/leonelquinteros/gotext
|
||||||
|
|
||||||
|
// a good example of using interface{}
|
||||||
|
// https://github.com/Jeffail/tunny
|
||||||
|
|
||||||
func onExit(err error) {
|
func onExit(err error) {
|
||||||
log.Println("Sleep for 1 second")
|
log.Println("Sleep for 1 second")
|
||||||
time.Sleep(1 * 1000 * 1000 * 1000)
|
time.Sleep(1 * 1000 * 1000 * 1000)
|
||||||
|
@ -86,6 +94,8 @@ func lookupAAAA(hostname string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
go handleErrors()
|
||||||
|
|
||||||
// This puts all the files in that directory in the binary
|
// This puts all the files in that directory in the binary
|
||||||
// This directory includes the default config file if there is not already one
|
// This directory includes the default config file if there is not already one
|
||||||
packrBox = packr.NewBox("./resources")
|
packrBox = packr.NewBox("./resources")
|
||||||
|
@ -167,3 +177,39 @@ func r() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
log.Println("init() WAS HERE")
|
||||||
|
log.Println("init() WAS HERE")
|
||||||
|
log.Println("init() WAS HERE")
|
||||||
|
|
||||||
|
errChan = make(chan interface{}, 3)
|
||||||
|
shell.InitCallback(handleShell) // asks for all the shell errors to be sent here
|
||||||
|
|
||||||
|
sigChan = make(chan os.Signal, 3)
|
||||||
|
signal.Notify(sigChan, syscall.SIGUSR1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// get's sent the return values and errors from git.wit.com/wit/shell/
|
||||||
|
func handleShell(err interface{}, ret int) {
|
||||||
|
log.Println("shell.Run() END Returned ", ret)
|
||||||
|
errChan <- err
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleErrors() {
|
||||||
|
for val := range errChan {
|
||||||
|
log.Println("handleErrors() val =", val)
|
||||||
|
log.Println("handleErrors() reflect.TypeOf(val) =", reflect.TypeOf(val))
|
||||||
|
log.Printf("handleErrors() val type T = %T\n", val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// trap signals
|
||||||
|
/*
|
||||||
|
go func() {
|
||||||
|
s := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(s, syscall.SIGQUIT)
|
||||||
|
<-s
|
||||||
|
panic("give me the stack")
|
||||||
|
}()
|
||||||
|
*/
|
||||||
|
|
Loading…
Reference in New Issue