【问题标题】:golang error: fatal error: all goroutines are asleep deadlockgolang 错误:致命错误:所有 goroutine 都处于休眠状态
【发布时间】:2017-09-24 18:05:23
【问题描述】:

我想在Go中开发一个简单的电子邮件发送器,但是遇到了一些问题,这是我的实际代码:

package main


import (
    "flag"
    "sync"
    "fmt"
)

var logLevel = 0

func sendEmail(try combo){
        fmt.Printf("test send %s %s %s\n", try.to, try.from, try.subject)
}

// where we actually do the work
func work(toSend chan combo, wg *sync.WaitGroup) {
    for send := range toSend {
        sendEmail(send)
    }

    // let the main thread know we're done
    wg.Done()
}

// the basic unit that we pass around
type combo struct {
    to       string
    from     string
    subject  string
    header   string
    body     string
    success bool
}


func main() {

    //defaults variables
    emailsList, smtpList        := "", ""  
    typeConnect, ConnFileName  := "", ""
    delimStart, delimEnd       := "_STARTSUB_", "_ENDSUB_"
    threads, bcc := 5,  1
    skip := 0
    logFile := ""

    // Args parse
    flag.StringVar(&emailsList, "e", "", "load email list (required)") 
    flag.StringVar(&smtpList, "s", "", "load smtp list - (required)")
    flag.IntVar(&bcc, "b", 1, "number of emails sent per connection")
    flag.IntVar(&threads,"t", 2, "run `N` attempts in parallel threads")
    flag.StringVar(&typeConnect, "c", "","direct - send emails directly through smtp\n"+"\tsocks - send emails through smtp via socks5 [requires -f argument]\n"+"\thosts - send emails through smtp via server's ip addresses [requires -f argument]\n")
    flag.StringVar(&ConnFileName, "f", "", "if sending via socks the list should contain socks5 proxies in the following formats\n"+"\tip:port\n"+"\tip:port:user:pass\n")
    flag.StringVar(&delimStart, "q", "_STARTSUB_", "start delimiter for subject.")
    flag.StringVar(&delimEnd, "w", "_ENDSUB_", "end delimiter for subject.")
    flag.IntVar(&skip, "l", 0, "skip first `n` lines of input")
    flag.StringVar(&logFile, "debug", "", "write debug output to `file`")
    flag.IntVar(&logLevel, "d", 0, "set debug `level`")

    flag.Parse()

    var wg sync.WaitGroup // keep track of the workers
    toSend := make(chan combo) // to the workers

    // initialize n workers
    wg.Add(int(threads))
    for i := 0; i < int(threads); i++ {
        go work(toSend, &wg)
    }

    for email := range StreamLines("EMAILS", emailsList, skip) {

        from := "info@testfrom.com"
        subject := "test subject"
        header := "test header"
        body   := "test boady"

        try := combo{email,from, subject, header, body, false}
        toSend <- try
    }

    wg.Wait()
    close(toSend)

    fmt.Println("Send emails Done!")
}

我正在尝试使用渠道将电子邮件传递给 golang 中的工作人员,并返回此错误:

F:\dev\GoLang\gitlab\EasySend>go run main.go usage.go utils.go  -e emails.txt
test send test@gmail.com info@testfrom.com test subject
test send test@gmail.com info@testfrom.com test subject
test send test@gmail.com info@testfrom.com test subject
test send test@gmail.com info@testfrom.com test subject
test send test@gmail.com info@testfrom.com test subject
test send test@gmail.com info@testfrom.com test subject
test send test@gmail.com info@testfrom.com test subject
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [semacquire]:
sync.runtime_Semacquire(0xc04204c0fc)
        C:/Go/src/runtime/sema.go:56 +0x40
sync.(*WaitGroup).Wait(0xc04204c0f0)
        C:/Go/src/sync/waitgroup.go:131 +0x79
main.main()
        F:/dev/GoLang/gitlab/EasySend/main.go:90 +0x7af

goroutine 18 [chan receive]:
main.work(0xc04203e0c0, 0xc04204c0f0)
        F:/dev/GoLang/gitlab/EasySend/main.go:19 +0x110
created by main.main
        F:/dev/GoLang/gitlab/EasySend/main.go:76 +0x5db

goroutine 19 [chan receive]:
main.work(0xc04203e0c0, 0xc04204c0f0)
        F:/dev/GoLang/gitlab/EasySend/main.go:19 +0x110
created by main.main
        F:/dev/GoLang/gitlab/EasySend/main.go:76 +0x5db
exit status 2

我想知道我错在哪里?方式返回此错误

“致命错误:所有 goroutine 都处于休眠状态 - 死锁!”

【问题讨论】:

    标签: go


    【解决方案1】:

    程序死锁是因为 main 正在等待 goroutines 完成,而 goroutines 正在等待通道上的工作。要解决此问题,请在 main 中交换这些行的顺序

    wg.Wait()
    close(toSend)
    

    close(toSend)
    wg.Wait()
    

    当通道关闭时,worker中通道上的for循环退出,worker调用wg.Done()。

    【讨论】:

      猜你喜欢
      • 2015-04-02
      • 1970-01-01
      • 1970-01-01
      • 2015-01-11
      • 2022-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多