beep icon indicating copy to clipboard operation
beep copied to clipboard

Segmentation Fault

Open cfair-beckman opened this issue 3 years ago • 5 comments

I have a program where I am trying to execute beep and sometimes I want to proceed to the next one before the first one is finished....when I do that (by calling the code to play the sound from a go routine) I end up getting a segmentation fault in the library. It does not happen EVERY time but it happens fairly often and is really reproducible....

fatal error: unexpected signal during runtime execution [signal SIGSEGV: segmentation violation code=0x1 addr=0x7ff1e8044 pc=0x7ff22632cc7a]

runtime stack: runtime.throw(0x924fd0, 0x2a) /usr/lib/go/src/runtime/panic.go:1116 +0x72 runtime.sigpanic() /usr/lib/go/src/runtime/signal_unix.go:704 +0x4ac

goroutine 291 [syscall]: runtime.cgocall(0x8323d0, 0xc000571d88, 0xc000358000) /usr/lib/go/src/runtime/cgocall.go:133 +0x5b fp=0xc000571d58 sp=0xc000571d20 pc=0x40831b github.com/hajimehoshi/oto._Cfunc_snd_pcm_writei(0x7ff1e80085c0, 0xc000358000, 0x5be, 0x0) _cgo_gotypes.go:162 +0x4e fp=0xc000571d88 sp=0xc000571d58 pc=0x81eb2e github.com/hajimehoshi/oto.(*driver).TryWrite.func1(0xc0008a40c0, 0xc0002ea000) /home/christopher/go/pkg/mod/github.com/hajimehoshi/[email protected]/driver_linux.go:140 +0xd6 fp=0xc000571dd0 sp=0xc000571d88 pc=0x81f856 github.com/hajimehoshi/oto.(*driver).TryWrite(0xc0008a40c0, 0xc0002ea0f0, 0x10, 0x8000, 0x100, 0x0, 0x0) /home/christopher/go/pkg/mod/github.com/hajimehoshi/[email protected]/driver_linux.go:140 +0x1d8 fp=0xc000571e60 sp=0xc000571dd0 pc=0x81f258 github.com/hajimehoshi/oto.(*driverWriter).Write(0xc0008d2200, 0xc0002ea000, 0x100, 0x8000, 0x0, 0x0, 0x0) /home/christopher/go/pkg/mod/github.com/hajimehoshi/[email protected]/context.go:136 +0x10c fp=0xc000571ef0 sp=0xc000571e60 pc=0x81deec io.copyBuffer(0xadbbe0, 0xc0008d2200, 0xadbc00, 0xc0008a4100, 0xc0002ea000, 0x8000, 0x8000, 0x0, 0x0, 0x46f701) /usr/lib/go/src/io/io.go:411 +0x206 fp=0xc000571f68 sp=0xc000571ef0 pc=0x47afa6 io.Copy(...) /usr/lib/go/src/io/io.go:368 github.com/hajimehoshi/oto.NewContext.func1(0xc0008d2220) /home/christopher/go/pkg/mod/github.com/hajimehoshi/[email protected]/context.go:79 +0x69 fp=0xc000571fd8 sp=0xc000571f68 pc=0x81f569 runtime.goexit() /usr/lib/go/src/runtime/asm_amd64.s:1374 +0x1 fp=0xc000571fe0 sp=0xc000571fd8 pc=0x46f701 created by github.com/hajimehoshi/oto.NewContext /home/christopher/go/pkg/mod/github.com/hajimehoshi/[email protected]/context.go:78 +0x250

goroutine 1 [syscall, locked to thread]: github.com/wailsapp/wails/lib/renderer/webview._Cfunc_CgoWebViewLoop(0x1af5830, 0x1, 0x0) _cgo_gotypes.go:187 +0x4d github.com/wailsapp/wails/lib/renderer/webview.(*webview).Loop.func1(0xc000532028, 0x1, 0x0) /home/christopher/go/pkg/mod/github.com/wailsapp/[email protected]/lib/renderer/webview/webview.go:279 +0x5d github.com/wailsapp/wails/lib/renderer/webview.(*webview).Loop(0xc000532028, 0x1, 0x1) /home/christopher/go/pkg/mod/github.com/wailsapp/[email protected]/lib/renderer/webview/webview.go:279 +0x34 github.com/wailsapp/wails/lib/renderer/webview.(*webview).Run(0xc000532028) /home/christopher/go/pkg/mod/github.com/wailsapp/[email protected]/lib/renderer/webview/webview.go:283 +0x30 github.com/wailsapp/wails/lib/renderer.(*WebView).Run(0xc00023a070, 0xaea4a0, 0xc00023a070) /home/christopher/go/pkg/mod/github.com/wailsapp/[email protected]/lib/renderer/webview.go:235 +0x1ce github.com/wailsapp/wails.(*App).start(0xc000530000, 0x0, 0x0) /home/christopher/go/pkg/mod/github.com/wailsapp/[email protected]/app.go:151 +0x59f github.com/wailsapp/wails.(*App).Run(0xc000530000, 0x86bd80, 0xa743b0) /home/christopher/go/pkg/mod/github.com/wailsapp/[email protected]/app.go:94 +0xb0 main.wailsBinding() /home/christopher/go/src/gitlab.com/chrisfair/latin-catholic-prayers/frontend_interface.go:121 +0x1f9 main.main() /home/christopher/go/src/gitlab.com/chrisfair/latin-catholic-prayers/main.go:14 +0x138

goroutine 38 [chan send, 1 minutes]: github.com/BurntSushi/xgb.(*Conn).generateXIds(0xc0000c4370) /home/christopher/go/pkg/mod/github.com/!burnt!sushi/[email protected]/xgb.go:253 +0x9e created by github.com/BurntSushi/xgb.postNewConn /home/christopher/go/pkg/mod/github.com/!burnt!sushi/[email protected]/xgb.go:130 +0x1a5

goroutine 39 [chan send, 1 minutes]: github.com/BurntSushi/xgb.(*Conn).generateSeqIds(0xc0000c4370) /home/christopher/go/pkg/mod/github.com/!burnt!sushi/[email protected]/xgb.go:278 +0x73 created by github.com/BurntSushi/xgb.postNewConn /home/christopher/go/pkg/mod/github.com/!burnt!sushi/[email protected]/xgb.go:131 +0x1c7

goroutine 22 [chan receive, 1 minutes]: github.com/syossan27/tebata.(*Tebata).listen(0xc0000a1050) /home/christopher/go/pkg/mod/github.com/syossan27/[email protected]/tebata.go:37 +0x31 created by github.com/syossan27/tebata.New /home/christopher/go/pkg/mod/github.com/syossan27/[email protected]/tebata.go:30 +0xdc

goroutine 66 [chan send, 1 minutes]: github.com/BurntSushi/xgb.(*Conn).generateXIds(0xc0000c42c0) /home/christopher/go/pkg/mod/github.com/!burnt!sushi/[email protected]/xgb.go:253 +0x9e created by github.com/BurntSushi/xgb.postNewConn /home/christopher/go/pkg/mod/github.com/!burnt!sushi/[email protected]/xgb.go:130 +0x1a5

goroutine 67 [chan send, 1 minutes]: github.com/BurntSushi/xgb.(*Conn).generateSeqIds(0xc0000c42c0) /home/christopher/go/pkg/mod/github.com/!burnt!sushi/[email protected]/xgb.go:278 +0x73 created by github.com/BurntSushi/xgb.postNewConn /home/christopher/go/pkg/mod/github.com/!burnt!sushi/[email protected]/xgb.go:131 +0x1c7

goroutine 14 [chan send, 1 minutes]: github.com/BurntSushi/xgb.(*Conn).generateSeqIds(0xc0000c4420) /home/christopher/go/pkg/mod/github.com/!burnt!sushi/[email protected]/xgb.go:278 +0x73 created by github.com/BurntSushi/xgb.postNewConn /home/christopher/go/pkg/mod/github.com/!burnt!sushi/[email protected]/xgb.go:131 +0x1c7

goroutine 13 [chan send, 1 minutes]: github.com/BurntSushi/xgb.(*Conn).generateXIds(0xc0000c4420) /home/christopher/go/pkg/mod/github.com/!burnt!sushi/[email protected]/xgb.go:253 +0x9e created by github.com/BurntSushi/xgb.postNewConn /home/christopher/go/pkg/mod/github.com/!burnt!sushi/[email protected]/xgb.go:130 +0x1a5

goroutine 42 [syscall, 1 minutes]: os/signal.signal_recv(0xa748c0) /usr/lib/go/src/runtime/sigqueue.go:147 +0x9d os/signal.loop() /usr/lib/go/src/os/signal/signal_unix.go:23 +0x25 created by os/signal.Notify.func1.1 /usr/lib/go/src/os/signal/signal.go:150 +0x45

goroutine 23 [select, 1 minutes]: github.com/wailsapp/wails/lib/event.(*Manager).Start.func1(0xc000094140) /home/christopher/go/pkg/mod/github.com/wailsapp/[email protected]/lib/event/manager.go:103 +0x19c created by github.com/wailsapp/wails/lib/event.(*Manager).Start /home/christopher/go/pkg/mod/github.com/wailsapp/[email protected]/lib/event/manager.go:99 +0x131

goroutine 24 [select]: github.com/wailsapp/wails/lib/ipc.(*Manager).Start.func1(0xc000524300, 0xae5880, 0xc0000b8960) /home/christopher/go/pkg/mod/github.com/wailsapp/[email protected]/lib/ipc/manager.go:56 +0xdd created by github.com/wailsapp/wails/lib/ipc.(*Manager).Start /home/christopher/go/pkg/mod/github.com/wailsapp/[email protected]/lib/ipc/manager.go:54 +0x16d

goroutine 294 [chan receive]: github.com/hajimehoshi/oto.(*Context).Close(0xc0008d2220, 0x0, 0x0) /home/christopher/go/pkg/mod/github.com/hajimehoshi/[email protected]/context.go:116 +0xe5 github.com/faiface/beep/speaker.Close() /home/christopher/go/pkg/mod/github.com/faiface/[email protected]/speaker/speaker.go:73 +0x55 github.com/faiface/beep/speaker.Init(0xac44, 0x113a, 0x0, 0x0) /home/christopher/go/pkg/mod/github.com/faiface/[email protected]/speaker/speaker.go:31 +0x75 main.playAudioFile(0xc00022c7e0, 0x69, 0x0, 0x0) /home/christopher/go/src/gitlab.com/chrisfair/latin-catholic-prayers/prayers.go:343 +0x145 main.PlayWordFromPrayer(0xc0006ce7e8, 0x3, 0xc000506050, 0x9, 0x8000, 0x8000) /home/christopher/go/src/gitlab.com/chrisfair/latin-catholic-prayers/prayers.go:310 +0xa6 main.playWord(0xc000506050, 0x9, 0xc0006ce7e8, 0x3) /home/christopher/go/src/gitlab.com/chrisfair/latin-catholic-prayers/frontend_interface.go:60 +0x4d created by main.checkAnswer /home/christopher/go/src/gitlab.com/chrisfair/latin-catholic-prayers/frontend_interface.go:27 +0x139

I am essentially just following your example for playing the ogg file....if you want to take a look at my source code I will give you viewing access to my private gitlab repo.

cfair-beckman avatar Oct 07 '20 04:10 cfair-beckman

Hi! My first instinct here is that (since you're running a lot of goroutines) you are using some parts of Beep concurrently without proper synchronization, causing race conditions, sometimes leading to a segfault. Would that be correct? Not all parts of Beep are safe to use concurrently without synchronization, in fact, most aren't.

Also, are you locking the speaker when mutating your streamers? (In case you do mutate them.)

faiface avatar Oct 07 '20 08:10 faiface

Yes that is correct. What I am trying to do is to use beep to play ogg files and those ogg files are being played when a user presses a button in a Vue app (I am using wails to connect the stuff up) Wails runs everything as a separate goroutine I believe when it connects. I used the example in your code to wrapper a function to play a sound.

func playAudioFile(name string) (err error) {
	f, err := os.Open(name)
	if err != nil {
		return err
	}
	streamer, format, err := vorbis.Decode(f)
	if err != nil {
		return err
	}
	defer streamer.Close()

	speaker.Init(format.SampleRate, format.SampleRate.N(time.Second/10))
	done := make(chan bool)
	speaker.Play(beep.Seq(streamer, beep.Callback(func() {
		done <- true
	})))
	<-done
	return
}

What I really want is if the user presses a button playing a sound for it to either play the sound immediately upon pressing the button or queing on a list to do it when the speaker is ready again.

cfair-beckman avatar Oct 07 '20 14:10 cfair-beckman

I can get around it without too much difficulty I just put a guard variable to indicate whether or not the audio file is currently playing....if it is refuse to execute any of the code I the function. That seems to work for me but the long and short is if the stream is changed while the speaker is already playing possible boomers....got it...thanks :)

cfair-beckman avatar Oct 07 '20 15:10 cfair-beckman

BTW I looked at some more of your example code and I implemented a queue and only initialize the speaker and and play on startup. Under that condition it works great. I have completely gotten around the issue with the segfaults. It just caught me offgaurd initially. Great library thanks a bunch :) I still think the segfaults are a potential issue but they are not too hard to prevent if I simply initialize once and play once (using the queue for pushing additional sounds instead of feeding it straight to the player).

cfair-beckman avatar Oct 09 '20 20:10 cfair-beckman

BTW I looked at some more of your example code and I implemented a queue and only initialize the speaker and and play on startup. Under that condition it works great. I have completely gotten around the issue with the segfaults. It just caught me offgaurd initially. Great library thanks a bunch :) I still think the segfaults are a potential issue but they are not too hard to prevent if I simply initialize once and play once (using the queue for pushing additional sounds instead of feeding it straight to the player).

Hi, I have exactly the same issue. You say, that you implemented a queue as part of the solution. Can you give me a hint on that, or share this particular code?

Many thanks.

pmoscode avatar Dec 25 '21 20:12 pmoscode