Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/cgo, runtime: panic error when using 'fmt' and dll #21138

Closed
czxichen opened this issue Jul 24, 2017 · 7 comments

Comments

Projects
None yet
5 participants
@czxichen
Copy link

commented Jul 24, 2017

Please answer these questions before submitting your issue. Thanks!

What version of Go are you using (go version)?

go version go1.9beta1 windows/amd64

What operating system and processor architecture are you using (go env)?

set GOARCH=amd64
set GOBIN=D:\GO\BIN
set GOEXE=.exe
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOOS=windows
set GOPATH=D:\code
set GORACE=
set GOROOT=D:\go
set GOTOOLDIR=D:\go\pkg\tool\windows_amd64
set GCCGO=gccgo
set CC=gcc
set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0 -fdebug-prefix-map=C:\Users\administrator\AppData\Local\Temp\go-build914327971=/tmp/go-build -gno-record-gcc-switches
set CXX=g++
set CGO_ENABLED=1
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2
set PKG_CONFIG=pkg-config

What did you do?

View the Windows process private memory

package main

/*
#include <windows.h>
#include <Psapi.h>

void CountPrivate(PSAPI_WORKING_SET_INFORMATION* workSetInfo,int* count)
{
 	int workSetPrivate = 0;
    for (ULONG_PTR i = 0; i < workSetInfo->NumberOfEntries; ++i)
    {
        if(!workSetInfo->WorkingSetInfo[i].Shared) // 如果不是共享页计数器+1
            workSetPrivate += 1;
    }
	*count = workSetPrivate;
}
*/
import "C"

import (
	"flag"
	"fmt"
	"syscall"
	"unsafe"
)

const LARGE_BUFFER_SIZE = 256 * 1024 * 1024

var (
	workSetInfo     C.PSAPI_WORKING_SET_INFORMATION
	psapi           = syscall.NewLazyDLL("Psapi.dll")
	QueryWorkingSet = psapi.NewProc("QueryWorkingSet")
)

func main() {
	pid := flag.Int("p", 0, "-p pid")
	flag.Parse()

	h, err := syscall.OpenProcess(0X0400|0X0010, false, uint32(*pid))
	if err != nil {
		return
	}
	defer syscall.CloseHandle(h)
	var size = Query(h) * syscall.Getpagesize() / 1024

	//There is no panic error using 'println("Memory:", size)' here
	fmt.Println("Memory:", size)
}

func Query(handle syscall.Handle) int {
	var bufferSize = 0x8000
	var buffer = make([]byte, bufferSize)
	for {
		r, _, _ := QueryWorkingSet.Call(uintptr(handle), uintptr(unsafe.Pointer(&buffer[0])), uintptr(bufferSize))
		if r == 0 {
			bufferSize *= 2
			if bufferSize > LARGE_BUFFER_SIZE {
				return 0
			}
			continue
		}
		break
	}

	var count C.int
	C.CountPrivate((*C.PSAPI_WORKING_SET_INFORMATION)(unsafe.Pointer(&buffer[0])), &count)
	return int(count)
}

What did you expect to see?

Is it my code problem? Or something else?

What did you see instead?

D:\code\20151023\src>src.exe -p 23140
runtime: nameOff 0xe4c base 0x29bf004 not in ranges:
        types 0x4a4240 etypes 0x4ea8f9
fatal error: runtime: name offset base pointer out of range

goroutine 1 [running]:
runtime.throw(0x4dd32c, 0x2e)
        D:/go/src/runtime/panic.go:605 +0x9c fp=0xc04206bd00 sp=0xc04206bce0 pc=0x42a64c
runtime.resolveNameOff(0x29bf004, 0xe4c, 0x8)
        D:/go/src/runtime/type.go:193 +0x255 fp=0xc04206bd68 sp=0xc04206bd00 pc=0x44a115
runtime.(*_type).nameOff(0x29bf004, 0xc000000e4c, 0xc04206bdc0)
        D:/go/src/runtime/type.go:199 +0x3a fp=0xc04206bd90 sp=0xc04206bd68 pc=0x44a22a
runtime.(*_type).string(0x29bf004, 0xc04206be08, 0x459a57)
        D:/go/src/runtime/type.go:46 +0x3d fp=0xc04206bdb8 sp=0xc04206bd90 pc=0x449ced
runtime.panicdottypeE(0x29bf004, 0x4cece0, 0x4bb8e0)
        D:/go/src/runtime/iface.go:170 +0x195 fp=0xc04206be18 sp=0xc04206bdb8 pc=0x40d855
fmt.newPrinter(0xc04204e0e0)
        D:/go/src/fmt/print.go:133 +0xc2 fp=0xc04206be48 sp=0xc04206be18 pc=0x495982
fmt.Fprintln(0x543180, 0xc04206e008, 0xc04206bf50, 0x2, 0x2, 0x4b4c80, 0xc04208a000, 0xc0420500e8)
        D:/go/src/fmt/print.go:246 +0x2d fp=0xc04206beb0 sp=0xc04206be48 pc=0x4960fd
fmt.Println(0xc04206bf50, 0x2, 0x2, 0xc0420500e8, 0x0, 0xc0420500b0)
        D:/go/src/fmt/print.go:257 +0x5e fp=0xc04206bf00 sp=0xc04206beb0 pc=0x49622e
main.main()
        D:/code/20151023/src/QueryWorkingSet.go:46 +0x18e fp=0xc04206bf80 sp=0xc04206bf00 pc=0x4a3f7e
runtime.main()
        D:/go/src/runtime/proc.go:185 +0x209 fp=0xc04206bfe0 sp=0xc04206bf80 pc=0x42bd69
runtime.goexit()
        D:/go/src/runtime/asm_amd64.s:2337 +0x1 fp=0xc04206bfe8 sp=0xc04206bfe0pc=0x451ec1
		
-----------------------------------------------------------------------------------------------------------
D:\code\20151023\src>src.exe -p 22928
unexpected fault address 0xadc502c
fatal error: fault
[signal 0xc0000005 code=0x0 addr=0xadc502c pc=0x449cdd]

goroutine 1 [running]:
runtime.throw(0x4d5f77, 0x5)
        D:/go/src/runtime/panic.go:605 +0x9c fp=0xc042061d60 sp=0xc042061d40 pc=0x42a64c
runtime.sigpanic()
        D:/go/src/runtime/signal_windows.go:164 +0x14e fp=0xc042061d90 sp=0xc042061d60 pc=0x43b3ee
runtime.(*_type).string(0xadc5004, 0xc042061e08, 0x459a57)
        D:/go/src/runtime/type.go:46 +0x2d fp=0xc042061db8 sp=0xc042061d90 pc=0x449cdd
runtime.panicdottypeE(0xadc5004, 0x4cece0, 0x4bb8e0)
        D:/go/src/runtime/iface.go:170 +0x195 fp=0xc042061e18 sp=0xc042061db8 pc=0x40d855
fmt.newPrinter(0xc042008400)
        D:/go/src/fmt/print.go:133 +0xc2 fp=0xc042061e48 sp=0xc042061e18 pc=0x495982
fmt.Fprintln(0x543180, 0xc042004018, 0xc042061f50, 0x2, 0x2, 0x4b4c80, 0xc042070000, 0xc04200e138)
        D:/go/src/fmt/print.go:246 +0x2d fp=0xc042061eb0 sp=0xc042061e48 pc=0x4960fd
fmt.Println(0xc042061f50, 0x2, 0x2, 0xc04200e138, 0x0, 0xc04200e0f8)
        D:/go/src/fmt/print.go:257 +0x5e fp=0xc042061f00 sp=0xc042061eb0 pc=0x49622e
main.main()
        D:/code/20151023/src/QueryWorkingSet.go:47 +0x18e fp=0xc042061f80 sp=0xc042061f00 pc=0x4a3f7e
runtime.main()
        D:/go/src/runtime/proc.go:185 +0x209 fp=0xc042061fe0 sp=0xc042061f80 pc=0x42bd69
runtime.goexit()
        D:/go/src/runtime/asm_amd64.s:2337 +0x1 fp=0xc042061fe8 sp=0xc042061fe0pc=0x451ec1

@odeke-em odeke-em changed the title Panic error occurred using 'fmt' in Cgo. cmd/cgo, runtime: panic error when using 'fmt' and dll Jul 24, 2017

@odeke-em

This comment has been minimized.

Copy link
Member

commented Jul 24, 2017

@czxichen for easier reproducibility and bug fixing, perhaps it might be helpful to post a link or a way of getting files Psapi.h and Psapi.dll.

Since this is a potential cmd/cgo and runtime issue, I'll page @ianlancetaylor and @aclements.

@czxichen

This comment has been minimized.

Copy link
Author

commented Jul 24, 2017

@odeke-em psapi.h and psapi.dll Download

@odeke-em

This comment has been minimized.

Copy link
Member

commented Jul 24, 2017

@czxichen unfortunately that returns a 404
screen shot 2017-07-24 at 3 05 16 am

@czxichen

This comment has been minimized.

Copy link
Author

commented Jul 24, 2017

@odeke-em I sent it to you by email(emm.odeke@gmail.com) attachment.

@cherrymui

This comment has been minimized.

Copy link
Contributor

commented Jul 24, 2017

The code looks a bit weird in that in the loop in func Query, it doubles bufferSize but doesn't allocate a larger buffer. This may cause memory corruption if QueryWorkingSet.Call writes bufferSize bytes. Did I miss something?

@czxichen

This comment has been minimized.

Copy link
Author

commented Jul 25, 2017

@cherrymui thanks,This mistake is too low.

@czxichen czxichen closed this Jul 25, 2017

@alexbrainman

This comment has been minimized.

Copy link
Member

commented Jul 26, 2017

This mistake is too low.

You have to be double careful when you use "unsafe" package.

Alex

@golang golang locked and limited conversation to collaborators Jul 26, 2018

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
You can’t perform that action at this time.