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

runtime: crash accessing C/C++ memory on Windows #54871

Closed
Logonz opened this issue Sep 5, 2022 · 6 comments
Closed

runtime: crash accessing C/C++ memory on Windows #54871

Logonz opened this issue Sep 5, 2022 · 6 comments
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. OS-Windows WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.
Milestone

Comments

@Logonz
Copy link

Logonz commented Sep 5, 2022

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

$ go version
go version go1.19 windows/amd64

Does this issue reproduce with the latest release?

Yes, it does not happen with release 1.16.X

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

go env Output
$ go env
set GO111MODULE=
set GOARCH=amd64
set GOBIN=
set GOCACHE=C:\Users\DavidHo\AppData\Local\go-build
set GOENV=C:\Users\DavidHo\AppData\Roaming\go\env
set GOEXE=.exe
set GOEXPERIMENT=
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOINSECURE=
set GOMODCACHE=C:\Users\DavidHo\go\pkg\mod
set GONOPROXY=
set GONOSUMDB=
set GOOS=windows
set GOPATH=C:\Users\DavidHo\go
set GOPRIVATE=
set GOPROXY=https://proxy.golang.org,direct
set GOROOT=C:\Program Files\Go
set GOSUMDB=sum.golang.org
set GOTMPDIR=
set GOTOOLDIR=C:\Program Files\Go\pkg\tool\windows_amd64
set GOVCS=
set GOVERSION=go1.19
set GCCGO=gccgo
set GOAMD64=v1
set AR=ar
set CC=gcc
set CXX=g++
set CGO_ENABLED=1
set GOMOD=NUL
set GOWORK=
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
set GOGCCFLAGS=-m64 -mthreads -fno-caret-diagnostics -Qunused-arguments -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=C:\Users\DavidHo\AppData\Local\Temp\go-build4245859064=/tmp/go-build -gno-record-gcc-switches

What did you do?

Source: https://github.com/Logonz/Muteiny
My program does some low-level windows calls to be able to control the microphone
Running it in the debugger works fine but as soon as you run the compiled version it crashes

func SetMute(aev *wca.IAudioEndpointVolume, mute bool) error {
	var currentMute bool
	if err := aev.GetMute(&currentMute); err != nil {
		return err
	}
	if currentMute != mute {
		if err := aev.SetMute(mute, nil); err != nil {
			fmt.Println("this row is required, huh?") //? If this row is not here, the program will crash when you try to mute the mic (it is not needed in golang 1.16)
			return err
		}
		if !mute {
			systray.SetTemplateIcon(icons.Mic, icons.Mic)
		} else {
			systray.SetTemplateIcon(icons.MicMute, icons.MicMute)
		}
		fmt.Printf("Mute State set to:%v\n", mute)
	}
	return nil
}

However it does not crash if you add the fmt.Println within the aev.SetMute error block. But as soon you remove the line it crashes again.
Compiling it with golang version 1.16 also works without the print function.

Crash message Output
Microphone Array (Realtek(R) Audio)
Start capturing keyboard input
Mute State: true
Down VK_A
unexpected fault address 0x17d42000000
fatal error: fault
[signal 0xc0000005 code=0x0 addr=0x17d42000000 pc=0x90e91e]

goroutine 6 [running]:
runtime.throw({0x95c93d?, 0xc000065d70?})
C:/Program Files/Go/src/runtime/panic.go:1047 +0x65 fp=0xc000065d50 sp=0xc000065d20 pc=0x7c7965
runtime.sigpanic()
C:/Program Files/Go/src/runtime/signal_windows.go:261 +0x125 fp=0xc000065d98 sp=0xc000065d50 pc=0x7dae05
github.com/moutend/go-wca/pkg/wca.(*IAudioEndpointVolume).VTable(...)
C:/Users/DavidHo/go/pkg/mod/github.com/moutend/go-wca@v0.2.0/pkg/wca/IAudioEndpointVolume.go:36
github.com/moutend/go-wca/pkg/wca.aevSetMute(0x83b414?, 0x18?, 0xc00018e040?)
C:/Users/DavidHo/go/pkg/mod/github.com/moutend/go-wca@v0.2.0/pkg/wca/IAudioEndpointVolume_windows.go:159 +0x1e fp=0xc000065de8 sp=0xc000065d98 pc=0x90e91e
github.com/moutend/go-wca/pkg/wca.(*IAudioEndpointVolume).SetMute(...)
C:/Users/DavidHo/go/pkg/mod/github.com/moutend/go-wca@v0.2.0/pkg/wca/IAudioEndpointVolume.go:95
main.SetMute(0x9c0900?, 0x0)
C:/jobb/Muteiny/muteiny.go:26 +0x56 fp=0xc000065e50 sp=0xc000065de8 pc=0x910656
main.runKeyboard(0x0?, {0xc0000160e0, 0x4})
C:/jobb/Muteiny/muteiny.go:239 +0x3de fp=0xc000065fa8 sp=0xc000065e50 pc=0x911efe
main.main.func2()
C:/jobb/Muteiny/muteiny.go:125 +0x2e fp=0xc000065fe0 sp=0xc000065fa8 pc=0x9110ce
runtime.goexit()
C:/Program Files/Go/src/runtime/asm_amd64.s:1594 +0x1 fp=0xc000065fe8 sp=0xc000065fe0 pc=0x7f4721
created by main.main
C:/jobb/Muteiny/muteiny.go:124 +0x745

goroutine 1 [syscall, locked to thread]:
runtime.cgocall(0x7f5fe0, 0xb06fa0)
C:/Program Files/Go/src/runtime/cgocall.go:158 +0x4a fp=0xc000115aa0 sp=0xc000115a68 pc=0x79416a
syscall.SyscallN(0x9894e8?, {0xc000115b38?, 0x7f0e3b?, 0x7ffc221adfd0?})
C:/Program Files/Go/src/runtime/syscall_windows.go:557 +0x109 fp=0xc000115b18 sp=0xc000115aa0 pc=0x7f1229
syscall.Syscall6(0x95e22e?, 0xb?, 0x17d42dd96b0?, 0x0?, 0x7ee0fa?, 0x0?, 0xc000115bc0?, 0x8f5746?)
C:/Program Files/Go/src/runtime/syscall_windows.go:501 +0x50 fp=0xc000115b78 sp=0xc000115b18 pc=0x7f0eb0
golang.org/x/sys/windows.(*Proc).Call(0x79d4e7?, {0xc00018a080?, 0x928740?, 0xb06601?})
C:/Users/DavidHo/go/pkg/mod/golang.org/x/sys@v0.0.0-20220829200755-d48e67d00261/windows/dll_windows.go:176 +0x1ca fp=0xc000115c30 sp=0xc000115b78 pc=0x8f4b8a
golang.org/x/sys/windows.(*LazyProc).Call(0xc00014e960, {0xc00018a080, 0x4, 0x4})
C:/Users/DavidHo/go/pkg/mod/golang.org/x/sys@v0.0.0-20220829200755-d48e67d00261/windows/dll_windows.go:348 +0x50 fp=0xc000115c60 sp=0xc000115c30 pc=0x8f57d0
github.com/getlantern/systray.nativeLoop()
C:/Users/DavidHo/go/pkg/mod/github.com/getlantern/systray@v1.2.1/systray_windows.go:792 +0xe5 fp=0xc000115cd0 sp=0xc000115c60 pc=0x905d85
github.com/getlantern/systray.Run(0x17d42c20880?, 0xc0000170c0?)
C:/Users/DavidHo/go/pkg/mod/github.com/getlantern/systray@v1.2.1/systray.go:78 +0x1e fp=0xc000115cf0 sp=0xc000115cd0 pc=0x902fde
main.main()
C:/jobb/Muteiny/muteiny.go:131 +0x753 fp=0xc000115f80 sp=0xc000115cf0 pc=0x910e93
runtime.main()
C:/Program Files/Go/src/runtime/proc.go:250 +0x1fe fp=0xc000115fe0 sp=0xc000115f80 pc=0x7ca09e
runtime.goexit()
C:/Program Files/Go/src/runtime/asm_amd64.s:1594 +0x1 fp=0xc000115fe8 sp=0xc000115fe0 pc=0x7f4721

goroutine 2 [force gc (idle)]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
C:/Program Files/Go/src/runtime/proc.go:363 +0xd6 fp=0xc000051fb0 sp=0xc000051f90 pc=0x7ca436
runtime.goparkunlock(...)
C:/Program Files/Go/src/runtime/proc.go:369
runtime.forcegchelper()
C:/Program Files/Go/src/runtime/proc.go:302 +0xb1 fp=0xc000051fe0 sp=0xc000051fb0 pc=0x7ca2d1
runtime.goexit()
C:/Program Files/Go/src/runtime/asm_amd64.s:1594 +0x1 fp=0xc000051fe8 sp=0xc000051fe0 pc=0x7f4721
created by runtime.init.6
C:/Program Files/Go/src/runtime/proc.go:290 +0x25

goroutine 3 [GC sweep wait]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
C:/Program Files/Go/src/runtime/proc.go:363 +0xd6 fp=0xc000053f90 sp=0xc000053f70 pc=0x7ca436
runtime.goparkunlock(...)
C:/Program Files/Go/src/runtime/proc.go:369
runtime.bgsweep(0x0?)
C:/Program Files/Go/src/runtime/mgcsweep.go:278 +0x8e fp=0xc000053fc8 sp=0xc000053f90 pc=0x7b478e
runtime.gcenable.func1()
C:/Program Files/Go/src/runtime/mgc.go:178 +0x26 fp=0xc000053fe0 sp=0xc000053fc8 pc=0x7a9526
runtime.goexit()
C:/Program Files/Go/src/runtime/asm_amd64.s:1594 +0x1 fp=0xc000053fe8 sp=0xc000053fe0 pc=0x7f4721
created by runtime.gcenable
C:/Program Files/Go/src/runtime/mgc.go:178 +0x6b

goroutine 4 [GC scavenge wait]:
runtime.gopark(0xc0000260e0?, 0x9bfbc0?, 0x1?, 0x0?, 0x0?)
C:/Program Files/Go/src/runtime/proc.go:363 +0xd6 fp=0xc000063f70 sp=0xc000063f50 pc=0x7ca436
runtime.goparkunlock(...)
C:/Program Files/Go/src/runtime/proc.go:369
runtime.(*scavengerState).park(0xb064c0)
C:/Program Files/Go/src/runtime/mgcscavenge.go:389 +0x53 fp=0xc000063fa0 sp=0xc000063f70 pc=0x7b2813
runtime.bgscavenge(0x0?)
C:/Program Files/Go/src/runtime/mgcscavenge.go:617 +0x45 fp=0xc000063fc8 sp=0xc000063fa0 pc=0x7b2e05
runtime.gcenable.func2()
C:/Program Files/Go/src/runtime/mgc.go:179 +0x26 fp=0xc000063fe0 sp=0xc000063fc8 pc=0x7a94c6
runtime.goexit()
C:/Program Files/Go/src/runtime/asm_amd64.s:1594 +0x1 fp=0xc000063fe8 sp=0xc000063fe0 pc=0x7f4721
created by runtime.gcenable
C:/Program Files/Go/src/runtime/mgc.go:179 +0xaa

goroutine 5 [finalizer wait]:
runtime.gopark(0x7ca7d7?, 0x7ca205?, 0x0?, 0x0?, 0xc000055f70?)
C:/Program Files/Go/src/runtime/proc.go:363 +0xd6 fp=0xc000055e28 sp=0xc000055e08 pc=0x7ca436
runtime.goparkunlock(...)
C:/Program Files/Go/src/runtime/proc.go:369
runtime.runfinq()
C:/Program Files/Go/src/runtime/mfinal.go:180 +0x10f fp=0xc000055fe0 sp=0xc000055e28 pc=0x7a862f
runtime.goexit()
C:/Program Files/Go/src/runtime/asm_amd64.s:1594 +0x1 fp=0xc000055fe8 sp=0xc000055fe0 pc=0x7f4721
created by runtime.createfing
C:/Program Files/Go/src/runtime/mfinal.go:157 +0x45

goroutine 18 [syscall, locked to thread]:
runtime.cgocall(0x7f5fe0, 0xc0000802c0)
C:/Program Files/Go/src/runtime/cgocall.go:158 +0x4a fp=0xc00008fed0 sp=0xc00008fe98 pc=0x79416a
syscall.SyscallN(0x4?, {0xc00018a020?, 0x79d4e7?, 0x20?})
C:/Program Files/Go/src/runtime/syscall_windows.go:557 +0x109 fp=0xc00008ff48 sp=0xc00008fed0 pc=0x7f1229
syscall.(*Proc).Call(0x9338a0?, {0xc00018a020?, 0x0?, 0x0?})
C:/Program Files/Go/src/syscall/dll_windows.go:190 +0x25 fp=0xc00008ff88 sp=0xc00008ff48 pc=0x819665
github.com/moutend/go-hook/pkg/win32.GetMessage(...)
C:/Users/DavidHo/go/pkg/mod/github.com/moutend/go-hook@v0.1.0/pkg/win32/win32_windows.go:47
github.com/moutend/go-hook/pkg/keyboard.install.func1()
C:/Users/DavidHo/go/pkg/mod/github.com/moutend/go-hook@v0.1.0/pkg/keyboard/keyboard_windows.go:67 +0xf6 fp=0xc00008ffe0 sp=0xc00008ff88 pc=0x90de96
runtime.goexit()
C:/Program Files/Go/src/runtime/asm_amd64.s:1594 +0x1 fp=0xc00008ffe8 sp=0xc00008ffe0 pc=0x7f4721
created by github.com/moutend/go-hook/pkg/keyboard.install
C:/Users/DavidHo/go/pkg/mod/github.com/moutend/go-hook@v0.1.0/pkg/keyboard/keyboard_windows.go:48 +0x110

goroutine 19 [syscall]:
runtime.notetsleepg(0x0?, 0x0?)
C:/Program Files/Go/src/runtime/lock_sema.go:294 +0x3c fp=0xc000091fa0 sp=0xc000091f58 pc=0x79bbfc
os/signal.signal_recv()
C:/Program Files/Go/src/runtime/sigqueue.go:152 +0x2f fp=0xc000091fc0 sp=0xc000091fa0 pc=0x7f022f
os/signal.loop()
C:/Program Files/Go/src/os/signal/signal_unix.go:23 +0x19 fp=0xc000091fe0 sp=0xc000091fc0 pc=0x84d3f9
runtime.goexit()
C:/Program Files/Go/src/runtime/asm_amd64.s:1594 +0x1 fp=0xc000091fe8 sp=0xc000091fe0 pc=0x7f4721
created by os/signal.Notify.func1.1
C:/Program Files/Go/src/os/signal/signal.go:151 +0x2a

goroutine 20 [chan receive]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
C:/Program Files/Go/src/runtime/proc.go:363 +0xd6 fp=0xc00008bed0 sp=0xc00008beb0 pc=0x7ca436
runtime.chanrecv(0xc0000ac1e0, 0x0, 0x1)
C:/Program Files/Go/src/runtime/chan.go:583 +0x49b fp=0xc00008bf60 sp=0xc00008bed0 pc=0x7967fb
runtime.chanrecv1(0x0?, 0x0?)
C:/Program Files/Go/src/runtime/chan.go:442 +0x18 fp=0xc00008bf88 sp=0xc00008bf60 pc=0x796338
main.onReady.func1()
C:/jobb/Muteiny/muteiny.go:162 +0x26 fp=0xc00008bfe0 sp=0xc00008bf88 pc=0x9115a6
runtime.goexit()
C:/Program Files/Go/src/runtime/asm_amd64.s:1594 +0x1 fp=0xc00008bfe8 sp=0xc00008bfe0 pc=0x7f4721
created by main.onReady
C:/jobb/Muteiny/muteiny.go:161 +0x236


Steps to reproduce:

Build the program
go build
./Muteiny.exe -k VK_A (Binds the A key on your keyboard)
Press A -> Crash happens

Add the fmt.Println line in the SetMute function as shown above
Rebuild
./Muteiny.exe -k VK_A (Binds the A key on your keyboard)
Press A 
Should work

PS. Your default microphone will be muted if you only crash the program
Remember to unmute it again by going into Control Panel -> Sound -> Recording -> Default Device -> Properties -> Levels to unmute

@beoran
Copy link

beoran commented Sep 5, 2022

Go is not C so you need to take several precautions.

You will probably have to lock the os thread:

https://github.com/golang/go/wiki/LockOSThread

And prevent the garbage collector from cleaning up the handles: https://pkg.go.dev/runtime#KeepAlive

If you want to use defer to close the handles you will have to wrap them in Go types as well. Hope this helps.

@mknyszek
Copy link
Contributor

mknyszek commented Sep 6, 2022

It's hard to say what's going wrong just from the information provided. The crash appears to be coming from an access to non-Go memory, so it's possible this is not a Go issue to begin with. I would suggest asking for help on https://groups.google.com/g/golang-nuts and coming back to the issue tracker once this definitely looks like a compiler/runtime issue.

It's possible, but just from a quick skim of the library there's enough room for user error that this needs a deeper investigation.

This may be some liveness issue or other kind of mishandling as @beoran suggests, but because it's specifically crashing in access to C/C++ memory I'm not positive (this becomes more likely if the memory is freed via a finalizer or something). I might suggest inserting calls to runtime.GC in various places. Trying to run this code on a locked OS thread to see if it reproduces also might be a good idea, as @beoran suggested.

@mknyszek mknyszek added OS-Windows WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided. NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. labels Sep 6, 2022
@mknyszek mknyszek changed the title Potential compiler bug (Windows) runtime: crash accessing C/C++ memory on Windows Sep 6, 2022
@mknyszek mknyszek added this to the Backlog milestone Sep 6, 2022
@gopherbot gopherbot added the compiler/runtime Issues related to the Go compiler and/or runtime. label Sep 6, 2022
@Logonz
Copy link
Author

Logonz commented Sep 7, 2022

I tested @beoran 's suggestion with the LockOSThread example and that seems to solve the issue, but if it's a workaround or expected behavior I can't really say anything about.
The only strange thing I would say is that it worked perfectly in 1.16 but not in 1.19.

@beoran
Copy link

beoran commented Sep 7, 2022

@Logonz I am more surprised it worked before in 1.16 without locking the thread, it is not a workaround but a necessary precaution since the Windows OS doesn't always support system calls from non main threads.

@Logonz
Copy link
Author

Logonz commented Sep 12, 2022

You learn something new everyday, thanks for the help and insight @beoran ! If it is expected behavior it can be closed from my point of view!

@joedian joedian closed this as completed Nov 16, 2022
@joedian
Copy link

joedian commented Nov 16, 2022

Resolved.

@golang golang locked and limited conversation to collaborators Nov 16, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. OS-Windows WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.
Projects
None yet
Development

No branches or pull requests

5 participants