Golang HelloActor出现致命错误:所有goroutine都处于休眠状态-死锁。

huangapple go评论96阅读模式
英文:

Golang HelloActor I fatal error: all goroutines are asleep - deadlock

问题

我有以下代码来测试使用Go 1.18的actor模型:

package main

import (
	"fmt"
	"sync"

	"github.com/AsynkronIT/protoactor-go/actor"
)

// Actor

type helloActor struct{}

func (*helloActor) Receive(context actor.Context) {
	switch msg := context.Message().(type) {
	case int:
		fmt.Println(msg)
	}
}

func main() {
	system := actor.NewActorSystem()
	props := actor.PropsFromProducer(func() actor.Actor { return &helloActor{} })

	pid := system.Root.Spawn(props)

	system.Root.Send(pid, 42)
	system.Root.Send(pid, 42)
	system.Root.Send(pid, 42)
	system.Root.Send(pid, 42)

	var wg sync.WaitGroup
	wg.Add(1)
	wg.Wait()
}

这段代码是由我的教授编写的,但由于某种原因,我收到了致命错误消息。其他遇到这个问题的人通常没有(正确地)关闭通道,但是actor模型不使用任何通道。通过调试,我发现程序在wg.Wait()处崩溃。在Wait方法中调用了semaquire函数,但程序随后崩溃。

以下是精确的错误输出:

PS C:\Users\mytho\go\Verteilte Softwaresysteme\labing\ob-22ss> go run Code/proto.actor/helloworld/helloworld.go
42
42
42
42
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [semacquire]:
sync.runtime_Semacquire(0x10?)
        C:/Program Files/Go/src/runtime/sema.go:56 +0x25
sync.(*WaitGroup).Wait(0xc000223320?)
        C:/Program Files/Go/src/sync/waitgroup.go:136 +0x52
main.main()
        C:/Users/mytho/go/Verteilte Softwaresysteme/labing/ob-22ss/Code/proto.actor/helloworld/helloworld.go:34 +0x14f

goroutine 6 [chan receive]:
github.com/AsynkronIT/protoactor-go/log.(*ioLogger).listenEvent(0xc000124480)
        C:/Users/mytho/go/pkg/mod/github.com/!asynkron!i!t/protoactor-go@v0.0.0-20220403033403-f313dba2c418/log/string_encoder.go:57 +0x6d
created by github.com/AsynkronIT/protoactor-go/log.init.1
        C:/Users/mytho/go/pkg/mod/github.com/!asynkron!i!t/protoactor-go@v0.0.0-20220403033403-f313dba2c418/log/string_encoder.go:39 +0x10a
exit status 2

注意:当调试helloactor.go时,会显示四个"42"消息。当运行它时,只会显示错误消息。

英文:

I have the following Code to test the actor-model with Go 1.18

package main

import (
    "fmt"
    "sync"

    "github.com/AsynkronIT/protoactor-go/actor"
)

// Actor

type helloActor struct{}

func (*helloActor) Receive(context actor.Context) {
    switch msg := context.Message().(type) {
    case int:
	    fmt.Println(msg)
    }
}

func main() {
    system := actor.NewActorSystem()
    props := actor.PropsFromProducer(func() actor.Actor { return &helloActor{} })

    pid := system.Root.Spawn(props)

    system.Root.Send(pid, 42)
    system.Root.Send(pid, 42)
    system.Root.Send(pid, 42)
    system.Root.Send(pid, 42)

    var wg sync.WaitGroup    
	wg.Add(1)
    wg.Wait()
}

This Code was written by my professor but for some reason I get the fatal error message. Other people who have this problem often don't (properly) close channels but the actor-model does not use any.
Through debugging I found out that the programm crashes at wg.Wait(). Within the Wait-method is a call of the semaquire function. But then the programm crashes.

Here is the exact error output:

PS C:\Users\mytho\go\Verteilte Softwaresysteme\labing\ob-22ss> go run Code/proto.actor/helloworld/helloworld.go
42
42
42
42
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [semacquire]:
sync.runtime_Semacquire(0x10?)
        C:/Program Files/Go/src/runtime/sema.go:56 +0x25
sync.(*WaitGroup).Wait(0xc000223320?)
        C:/Program Files/Go/src/sync/waitgroup.go:136 +0x52
main.main()
        C:/Users/mytho/go/Verteilte Softwaresysteme/labing/ob-               2            
2ss/Code/proto.actor/helloworld/helloworld.go:34 +0x14f   

goroutine 6 [chan receive]:
github.com/AsynkronIT/protoactor-go/log.(*ioLogger).listenEvent(0xc000124480)
        C:/Users/mytho/go/pkg/mod/github.com/!asynkron!i!t/protoactor-go@v0.0.0- 
20220403033403-f313dba2c418/log/string_encoder.go:57 +0x6d
created by github.com/AsynkronIT/protoactor-go/log.init.1
        C:/Users/mytho/go/pkg/mod/github.com/!asynkron!i!t/protoactor-go@v0.0.0- 
20220403033403-f313dba2c418/log/string_encoder.go:39 +0x10a
     exit status 2

NOTE: the four "42" messages are only shown when the helloactor.go is debugged. When it is being runned it only shows the error-message.

答案1

得分: 1

var wg sync.WaitGroup
wg.Add(1)
wg.Done()
wg.Wait()

你没有调用wg.Done()来减少WaitGroup计数器。

PS:sync.WaitGroup用于在主goroutine完成之前等待其他goroutine完成。但在你的代码中,你没有创建任何其他的goroutine,所以它没有用处。
参考文档:https://pkg.go.dev/sync#WaitGroup

英文:
var wg sync.WaitGroup    
wg.Add(1)
wg.Done()
wg.Wait()

You are not calling wg.Done() to decrement the WaitGroup counter.

PS: sync.WaitGroup is used to wait for goroutines to finish before the main goroutine completes. But in your code, you are not spawning any other goroutine so it has no use.
For reference, check https://pkg.go.dev/sync#WaitGroup

答案2

得分: 0

wg.Wait()在没有wg.Done()的情况下会永远休眠。

看起来你想要一个阻塞的效果,对吗?
只需使用fmt.Scanf函数,它会一直阻塞IO,直到你输入回车键。
例如:

fmt.Println("输入回车键退出")
fmt.Scanf(" ")
英文:

The wg.Wait() will sleep forever without wg.Done().

It seems that you want a blocking, right?
Just use the fmt.Scanf function, it will keep io blocking until you type Enter.
For example:

fmt.Println("type enter to exit")
fmt.Scanf(" ")

huangapple
  • 本文由 发表于 2022年4月16日 04:29:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/71888666.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定