Пример #1
0
func caller() {
	//FIXME add a test to make sure file, pc from Callers matches
	// the equivalent from Caller.
	for i := 0; i < 2; i++ {
		_, _, _, ok := runtime.Caller(i)
		if !ok {
			panic(i)
		}
	}
	_, _, _, ok := runtime.Caller(20)
	if ok {
		panic(3)
	}
	pcA := make([]uintptr, 6, 6)
	count := runtime.Callers(0, pcA)
	pcB := make([]uintptr, 6, 6)
	countM1 := runtime.Callers(1, pcB)
	if count-1 != countM1 {
		panic(5)
	}
	for i := 1; i < countM1-1; i++ {
		if pcA[i+1] != pcB[i] {
			panic(100 + i)
		}
	}
}
Пример #2
0
func NewRecord(level Level, message string) *Record {
	record := &Record{
		Level:   level,
		Message: message,
	}
	record.Time = time.Now()
	var pcs [2]uintptr
	numStack := runtime.Callers(4, pcs[:])
	for i := 0; i < numStack; i += 1 {
		function := runtime.FuncForPC(pcs[i])
		if function == nil {
			break
		}
		filename, line := function.FileLine(pcs[i])
		if filename == srcFile {
			continue
		} else {
			record.FileName = filename
			record.LineNo = line
			record.FuncName = function.Name()
			break
		}
	}

	return record
}
Пример #3
0
func formatCallpath(calldepth int) string {
	v := ""
	callers := make([]uintptr, 64)
	n := runtime.Callers(calldepth+2, callers)
	oldPc := callers[n-1]

	recursiveCall := false
	for i := n - 3; i >= 0; i-- {
		pc := callers[i]
		if oldPc == pc {
			recursiveCall = true
			continue
		}
		oldPc = pc
		if recursiveCall {
			recursiveCall = false
			v += ".."
		}
		if i < n-3 {
			v += "."
		}
		if f := runtime.FuncForPC(pc); f != nil {
			v += formatFuncName(fmtVerbShortfunc, f.Name())
		}
	}
	return v
}
Пример #4
0
// VDepth reports whether verbosity at the call site is at least the requested
// level.
func VDepth(level level, depth int) bool {
	// This function tries hard to be cheap unless there's work to do.
	// The fast path is two atomic loads and compares.

	// Here is a cheap but safe test to see if V logging is enabled globally.
	if logging.verbosity.get() >= level {
		return true
	}

	// It's off globally but it vmodule may still be set.
	// Here is another cheap but safe test to see if vmodule is enabled.
	if atomic.LoadInt32(&logging.filterLength) > 0 {
		// Now we need a proper lock to use the logging structure. The pcs field
		// is shared so we must lock before accessing it. This is fairly expensive,
		// but if V logging is enabled we're slow anyway.
		logging.mu.Lock()
		defer logging.mu.Unlock()
		if runtime.Callers(2+depth, logging.pcs[:]) == 0 {
			return false
		}
		v, ok := logging.vmap[logging.pcs[0]]
		if !ok {
			v = logging.setV(logging.pcs[0])
		}
		return v >= level
	}
	return false
}
Пример #5
0
// Generates a stack from runtime.Callers()
func stackFrames(skip int, ignoreRuntime bool) []*frameInfo {
	frames := []*frameInfo{}
	size := 20
	pcs := make([]uintptr, size)
	// always skip the first frame, since it's runtime.Callers itself
	pcs = pcs[:runtime.Callers(1+skip, pcs)]

	for _, pc := range pcs {
		fn := runtime.FuncForPC(pc)
		name := fn.Name()
		file, line := fn.FileLine(pc - 1)
		if ignoreRuntime && strings.Contains(file, filepath.Join("src", "runtime")) {
			break
		}

		ci := &frameInfo{
			filename: file,
			lineno:   line,
			method:   name,
			pc:       pc,
		}

		frames = append(frames, ci)
	}
	return frames
}
Пример #6
0
func identifyPanic() string {
	var name, file string
	var line int
	var pc [16]uintptr

	n := runtime.Callers(3, pc[:])
	for _, pc := range pc[:n] {
		fn := runtime.FuncForPC(pc)
		if fn == nil {
			continue
		}
		file, line = fn.FileLine(pc)
		name = fn.Name()
		if !strings.HasPrefix(name, "runtime.") {
			break
		}
	}

	switch {
	case name != "":
		return fmt.Sprintf("%v:%v", name, line)
	case file != "":
		return fmt.Sprintf("%v:%v", file, line)
	}

	return fmt.Sprintf("pc:%x", pc)
}
Пример #7
0
// getPanic returns the number of frames to skip and the PC
// for the uppermost panic in the call stack (there might be
// multiple panics when a recover() catches a panic and then
// panics again). The second value indicates how many stack frames
// should be skipped in the stacktrace (they might not always match).
// The last return value indicates a frame could be found.
func getPanic() (int, int, uintptr, bool) {
	skip := 0
	callers := make([]uintptr, 10)
	for {
		calls := callers[:runtime.Callers(skip, callers)]
		c := len(calls)
		if c == 0 {
			break
		}
		for ii := c - 1; ii >= 0; ii-- {
			f := runtime.FuncForPC(calls[ii])
			if f != nil {
				name := f.Name()
				if strings.HasPrefix(name, "runtime.") && strings.Contains(name, "panic") {
					pcSkip := skip + ii - 1
					stackSkip := pcSkip
					switch name {
					case "runtime.panic":
					case "runtime.sigpanic":
						stackSkip -= 2
					default:
						stackSkip--
					}
					return pcSkip, stackSkip, calls[ii], true
				}
			}
		}
		skip += c
	}
	return 0, 0, 0, false
}
Пример #8
0
func getCaller() string {
	pc := make([]uintptr, 10) // at least 1 entry needed
	runtime.Callers(3, pc)
	f := runtime.FuncForPC(pc[0])
	return f.Name()

}
Пример #9
0
func Warn(v ...interface{}) {
	if logobj.level <= WARN {
		pc := make([]uintptr, 1)
		runtime.Callers(2, pc)
		logobj.output("WARN", pc[0], v...)
	}
}
Пример #10
0
func Info(v ...interface{}) {
	if logobj.level <= INFO {
		pc := make([]uintptr, 1)
		runtime.Callers(2, pc)
		logobj.output("INFO", pc[0], v...)
	}
}
Пример #11
0
func Debug(v ...interface{}) {
	if logobj.level <= DEBUG {
		pc := make([]uintptr, 1)
		runtime.Callers(2, pc) // 层次越深 性能越差
		logobj.output("DEBUG", pc[0], v...)
	}
}
Пример #12
0
func (self *ErrorField) format(e *Event) string {
	if e.Error == nil {
		return ""
	}

	var buffer bytes.Buffer

	callers := make([]uintptr, 20)
	n := runtime.Callers(3, callers) // starts in (*Logger).Log or similar
	callers = callers[:n]

	buffer.WriteString("\n")
	errorType := reflect.TypeOf(e.Error)
	buffer.WriteString(errorType.String() + ": ")
	buffer.WriteString(e.Error.Error())
	for _, pc := range callers {
		f := runtime.FuncForPC(pc)
		if !strings.Contains(f.Name(), "/slf4g/") {
			pathname, lineno := f.FileLine(pc)
			filename := path.Base(pathname)

			s := fmt.Sprintf("\n    at %s (%s:%d)", f.Name(), filename, lineno)
			buffer.WriteString(s)
		}
	}

	return buffer.String()
}
Пример #13
0
func Fail(message string) {
	log.Error("Failed assertion: %v", message)

	var buffer bytes.Buffer

	callers := make([]uintptr, 20)
	skip := 1
	n := runtime.Callers(skip, callers)
	callers = callers[:n]

	buffer.WriteString("Assertion failed")
	buffer.WriteString("\n")
	for _, pc := range callers {
		f := runtime.FuncForPC(pc)
		//if !strings.Contains(f.Name(), "/gova/log/")
		{
			pathname, lineno := f.FileLine(pc)
			filename := path.Base(pathname)

			s := fmt.Sprintf("\n    at %s (%s:%d)", f.Name(), filename, lineno)
			buffer.WriteString(s)
		}
	}

	log.Error(buffer.String())

	// TODO: Should we panic?
	panic("Assertion failed: " + buffer.String())
}
Пример #14
0
// callerName returns the package path and function name of the calling
// function.  The skip argument has the same meaning as the skip argument of
// runtime.Callers.
func callerName(skip int) (pkgPath, funcName string, ok bool) {
	var pc [1]uintptr
	n := runtime.Callers(skip+1, pc[:])
	if n != 1 {
		return "", "", false
	}

	f := runtime.FuncForPC(pc[0])
	fullName := f.Name()

	lastDotIndex := strings.LastIndex(fullName, ".")
	if lastDotIndex == -1 {
		panic("unable to distinguish function name from package")
	}

	if fullName[lastDotIndex-1] == ')' {
		// The caller is a method on some type, so it's name looks like
		// "pkg/path.(type).method".  We need to go back one dot farther to get
		// to the package name.
		lastDotIndex = strings.LastIndex(fullName[:lastDotIndex], ".")
	}

	pkgPath = fullName[:lastDotIndex]
	funcName = fullName[lastDotIndex+1:]
	ok = true
	return
}
Пример #15
0
func recordDBConn(path string, db *gouchstore.Gouchstore) {
	callers := make([]uintptr, 32)
	n := runtime.Callers(2, callers)
	openConnLock.Lock()
	openConns[db] = dbOpenState{path, frameSnap(callers[:n-1])}
	openConnLock.Unlock()
}
Пример #16
0
// NewStorageError - return new Error type.
func traceError(e error, errs ...error) error {
	if e == nil {
		return nil
	}
	err := &Error{}
	err.e = e
	err.errs = errs

	stack := make([]uintptr, 40)
	length := runtime.Callers(2, stack)
	if length > len(stack) {
		length = len(stack)
	}
	stack = stack[:length]

	for _, pc := range stack {
		pc = pc - 1
		fn := runtime.FuncForPC(pc)
		file, line := fn.FileLine(pc)
		name := fn.Name()
		if strings.HasSuffix(name, "ServeHTTP") {
			break
		}
		if strings.HasSuffix(name, "runtime.") {
			break
		}

		file = strings.TrimPrefix(file, rootPath+string(os.PathSeparator))
		name = strings.TrimPrefix(name, "github.com/minio/minio/cmd.")
		err.trace = append(err.trace, traceInfo{file, line, name})
	}

	return err
}
Пример #17
0
func (h ErrorHandler) recovery(w http.ResponseWriter, r *http.Request) {
	rec := recover()
	if rec == nil {
		return
	}

	// Obtain source of panic
	// From: https://gist.github.com/swdunlop/9629168
	var name, file string // function name, file name
	var line int
	var pc [16]uintptr
	n := runtime.Callers(3, pc[:])
	for _, pc := range pc[:n] {
		fn := runtime.FuncForPC(pc)
		if fn == nil {
			continue
		}
		file, line = fn.FileLine(pc)
		name = fn.Name()
		if !strings.HasPrefix(name, "runtime.") {
			break
		}
	}

	// Trim file path
	delim := "/caddy/"
	pkgPathPos := strings.Index(file, delim)
	if pkgPathPos > -1 && len(file) > pkgPathPos+len(delim) {
		file = file[pkgPathPos+len(delim):]
	}

	// Currently we don't use the function name, as file:line is more conventional
	h.Log.Printf("%s [PANIC %s] %s:%d - %v", time.Now().Format(timeFormat), r.URL.String(), file, line, rec)
	h.errorPage(w, http.StatusInternalServerError)
}
Пример #18
0
func Fatal(v ...interface{}) {
	if logobj.level <= FATAL {
		pc := make([]uintptr, 1)
		runtime.Callers(2, pc)
		logobj.output("FATAL", pc[0], v...)
	}
}
Пример #19
0
// Wrap makes an Error from the given value. If that value is already an
// error then it will be used directly, if not, it will be passed to
// fmt.Errorf("%v"). The skip parameter indicates how far up the stack
// to start the stacktrace. 0 is from the current call, 1 from its caller, etc.
func Wrap(e interface{}, skip int) *Error {
	var err error

	switch e := e.(type) {
	case *Error:
		return e
	case error:
		err = e
	default:
		err = fmt.Errorf("%v", e)
	}

	s := make([]uintptr, MaxStackDepth)
	length := runtime.Callers(2+skip, s[:])
	f := stackFrames(s[:length])
	return &Error{
		Err:    err,
		stack:  s[:length],
		frames: f,
		//	StackTrace: string(stack(f)),
		Stack:       errorStack(typeName(err), err, stack(f)),
		Description: err.Error(),
		Title:       err.Error(),
	}
}
Пример #20
0
func NewRecord(s string, l LogLevel, m string, d map[string]interface{}) *Record {
	r := &Record{
		Timestamp: RecordTimestamp(time.Now().UnixNano()) / 1000000000,
		Pid:       pid,
		Source:    s,
		Level:     l,
		Message:   m,
		Data:      d,
	}

	if config.EnableLOC {
		var function *runtime.Func
		var file string
		var line int

		pc := make([]uintptr, 50)
		nptrs := runtime.Callers(2, pc)
		for i := 0; i < nptrs; i++ {
			function = runtime.FuncForPC(pc[i])
			file, line = function.FileLine(pc[i])
			if !strings.HasSuffix(file, "logger.go") {
				break
			}
		}
		r.File = file
		r.Line = line
		r.Method = function.Name()
	}

	return r
}
Пример #21
0
//gets name of function that called the currently executing function.
func myCallerName() string {
	fpcs := make([]uintptr, 1)
	runtime.Callers(3, fpcs)
	fun := runtime.FuncForPC(fpcs[0])
	nameSplit := strings.Split(fun.Name(), ".")
	return nameSplit[len(nameSplit)-1]
}
Пример #22
0
func callers() *stack {
	const depth = 32
	var pcs [depth]uintptr
	n := runtime.Callers(3, pcs[:])
	var st stack = pcs[0:n]
	return &st
}
Пример #23
0
func (w *Writer) startLine(n Line, nn *int64, err *error) {
	if *err != nil {
		return
	}

	if _, ok := w.taken[n]; ok {
		panic("bitgen: duplicate line number")
	}
	var pc [64]uint64
	if *flagMap != "" {
		var pcnative [len(pc)]uintptr
		if i := runtime.Callers(1, pcnative[:]); i >= len(pc) {
			panic("call stack too deep for profile")
		}
		for i, n := range pcnative {
			pc[i] = uint64(n)
		}
	}
	w.taken[n] = pc
	if n == Line(*flagCrashOnLine) {
		panic("DEBUG")
	}

	write(w.w, "LINE NUMBER ", nn, err)
	number(w.w, uint64(n), nn, err)
	write(w.w, " CODE ", nn, err)
}
Пример #24
0
func getStackTraceMessage(msg string) string {
	var name, file string
	var line int
	var pc [16]uintptr

	n := runtime.Callers(3, pc[:])
	buff := &bytes.Buffer{}
	buff.WriteString(msg)
	buff.WriteString("\n")

	for _, pc := range pc[:n] {
		fn := runtime.FuncForPC(pc)
		if fn == nil {
			continue
		}
		file, line = fn.FileLine(pc)
		name = fn.Name()
		switch {
		case name != "":
			buff.WriteString(fmt.Sprintf("! %v:%v\n", name, line))
		case file != "":
			buff.WriteString(fmt.Sprintf("! %v:%v\n", file, line))
		}
	}
	return string(buff.Bytes())
}
Пример #25
0
func DumpEtcdOnFailure(t *testing.T) {
	if !t.Failed() {
		return
	}

	pc := make([]uintptr, 10)
	goruntime.Callers(2, pc)
	f := goruntime.FuncForPC(pc[0])
	last := strings.LastIndex(f.Name(), "Test")
	if last == -1 {
		last = 0
	}
	name := f.Name()[last:]

	client := NewEtcdClient()
	etcdResponse, err := client.RawGet("/", false, true)
	if err != nil {
		t.Logf("error dumping etcd: %v", err)
		return
	}

	if err := ioutil.WriteFile(GetBaseDir()+"/etcd-dump-"+name+".json", etcdResponse.Body, os.FileMode(0444)); err != nil {
		t.Logf("error dumping etcd: %v", err)
		return
	}
}
Пример #26
0
func NewTrace(skip int) *Trace {
	stack := make([]uintptr, MaxStackDepth)
	length := runtime.Callers(2+skip, stack)
	return &Trace{
		stack: stack[:length],
	}
}
Пример #27
0
// When a test is skipped or fails, runtime.Goexit() is called which destroys the callstack.
// This means the name of the test case is lost, so we need to grab a copy of pc before.
func Report(t testing.TB) {
	// If the goroutine panics, Fatal()s, or Skip()s, the function name is at the 3rd callstack
	// layer.  On success, its at 1st.  Since it's hard to check which happened, just try both.
	pcs := make([]uintptr, 10)
	total := runtime.Callers(1, pcs)
	var name string
	for _, pc := range pcs[:total] {
		fn := runtime.FuncForPC(pc)
		fullName := fn.Name()
		if strings.HasPrefix(path.Ext(fullName), ".Test") {
			// Skip the leading .
			name = string([]byte(path.Ext(fullName))[1:])
			break
		}
	}
	if name == "" {
		return
	}

	allCaseInfos.lock.Lock()
	defer allCaseInfos.lock.Unlock()
	allCaseInfos.Cases = append(allCaseInfos.Cases, &caseInfo{
		Name:    name,
		Passed:  !t.Failed() && !t.Skipped(),
		Skipped: t.Skipped(),
		Fatal:   t.Failed() && !strings.HasPrefix(name, "TestSoon"),
	})
}
Пример #28
0
func stacktrace() StackTrace {
	const depth = 8
	var pcs [depth]uintptr
	n := runtime.Callers(1, pcs[:])
	var st stack = pcs[0:n]
	return st.StackTrace()
}
Пример #29
0
Файл: main.go Проект: BVNK/bank
func trace() (funcTrace string) {
	pc := make([]uintptr, 10) // at least 1 entry needed
	runtime.Callers(2, pc)
	f := runtime.FuncForPC(pc[0])
	file, line := f.FileLine(pc[0])
	return fmt.Sprintf("%s:%d %s", file, line, f.Name())
}
Пример #30
0
func f3(pan bool) []uintptr {
	if pan {
		panic("f3") // line 23
	}
	ret := make([]uintptr, 20)
	return ret[:runtime.Callers(0, ret)] // line 26
}