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
|
||||
|
||||
// This should build and upload the binary to mirrors
|
||||
|
||||
import "log"
|
||||
// import "fmt"
|
||||
import "os"
|
||||
|
@ -20,7 +22,22 @@ var builddir string
|
|||
var homedir string
|
||||
|
||||
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()
|
||||
|
||||
|
@ -36,39 +53,13 @@ func main() {
|
|||
shell.Run("pwd")
|
||||
|
||||
for {
|
||||
time.Sleep(time.Second * 5)
|
||||
build()
|
||||
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() {
|
||||
// shell.SetDelayInMsec(50)
|
||||
shell.Run("go get -v .")
|
||||
|
@ -91,7 +82,6 @@ func ping() {
|
|||
shell.Run("ping -c 6 localhost")
|
||||
}
|
||||
|
||||
|
||||
// func setupUser() string, string, string {
|
||||
func setupUser() {
|
||||
// look up the user information
|
||||
|
|
29
config.go
29
config.go
|
@ -16,10 +16,12 @@ import "os/user"
|
|||
import "flag"
|
||||
import "fmt"
|
||||
import "runtime"
|
||||
// import "runtime/debug"
|
||||
import "io/ioutil"
|
||||
import "strings"
|
||||
import "reflect"
|
||||
import "bytes"
|
||||
// import "sys"
|
||||
|
||||
import "github.com/golang/protobuf/jsonpb"
|
||||
import pb "git.wit.com/wit/witProtobuf"
|
||||
|
@ -271,6 +273,33 @@ func parseConfig() {
|
|||
log.Println("config.Gitref =", config.Gitref)
|
||||
log.Println("config.Goversion =", config.Goversion)
|
||||
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 {
|
||||
|
|
|
@ -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 "os"
|
||||
import "time"
|
||||
// import "reflect"
|
||||
import "reflect"
|
||||
import "os/signal"
|
||||
import "syscall"
|
||||
|
||||
// this is the king of dns libraries
|
||||
import "github.com/miekg/dns"
|
||||
|
@ -11,6 +13,7 @@ import "github.com/miekg/dns"
|
|||
import "git.wit.com/wit/gui"
|
||||
import pb "git.wit.com/wit/witProtobuf"
|
||||
import "git.wit.com/jcarr/dnssecsocket"
|
||||
import "git.wit.com/wit/shell"
|
||||
|
||||
import "github.com/gobuffalo/packr"
|
||||
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 State string // used as a State machine
|
||||
var sigChan chan os.Signal
|
||||
var errChan chan interface{}
|
||||
|
||||
type myButtonInfo struct {
|
||||
Account *pb.Account // associated with what account?
|
||||
|
@ -57,6 +62,9 @@ type myButtonInfo struct {
|
|||
// i18n with 'po' file support
|
||||
// https://github.com/leonelquinteros/gotext
|
||||
|
||||
// a good example of using interface{}
|
||||
// https://github.com/Jeffail/tunny
|
||||
|
||||
func onExit(err error) {
|
||||
log.Println("Sleep for 1 second")
|
||||
time.Sleep(1 * 1000 * 1000 * 1000)
|
||||
|
@ -86,6 +94,8 @@ func lookupAAAA(hostname string) string {
|
|||
}
|
||||
|
||||
func main() {
|
||||
go handleErrors()
|
||||
|
||||
// This puts all the files in that directory in the binary
|
||||
// This directory includes the default config file if there is not already one
|
||||
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