S
S
Sergey Ilyin2021-09-17 12:27:05
go
Sergey Ilyin, 2021-09-17 12:27:05

Deadlock - a blockage occurs, what causes it?

Hello guys! I am new to Go. I've been sitting for 4 days now and I can't figure out what I'm doing wrong. The task is this: data is passed to the input, hashed and passed further to the MultiHash function, then MultiHash must read them again, hash them and pass them to the next function (the next function has not yet been implemented). An attempt to implement a pipeline, in the MultiHash function I try to read the data from the channel, but I get a deadlock. At what stage am I making a mistake?
I see on which lines there are problems, but I can’t understand in what order to parse them and how to make it all work

signer.go

package main

import (
  "fmt"
  "os"
  "sync"
)

// сюда писать код

func SingleHash(done chan interface{}, in []string) {

  defer close(done)

  fmt.Println(in)
  wg := &sync.WaitGroup{}
  mu := &sync.Mutex{}

  for _, i := range in {
    wg.Add(1)
    go workerSingleHash(wg, mu, i, done)
  }

  wg.Wait()
  fmt.Println("end singlehash")

}

func workerSingleHash(wg *sync.WaitGroup, mu *sync.Mutex, in string, done chan interface{}) {
  fmt.Println(in)
  defer wg.Done()

  crc32Chan := make(chan string)

  mu.Lock()
  md5Data := DataSignerMd5(in)
  mu.Unlock()

  go asyncCrc32Signer(in, crc32Chan)

  crc32Data := <-crc32Chan
  crc32Md5Data := DataSignerCrc32(md5Data)

  done <- crc32Data + "~" + crc32Md5Data

}

func asyncCrc32Signer(data string, out chan string) {
  defer close(out)

  out <- DataSignerCrc32(data)
}

func main() {
  done := make(chan interface{})
  
  in := os.Args

  SingleHash(done, in[1:])

  go func(done chan interface{}) {
    for v := range done {
      fmt.Println(v)
    }
  }(done)
}


These are functions that hash, DataSignerCrc32 cannot be used immediately one by one, as overheating occurs, they need to be parallelized. this file is not mine - this is a condition and I dealt with it, but this is not the problem, I just post it so that they can understand what these
common.go functions are
package main

import (
  "crypto/md5"
  "fmt"
  "hash/crc32"
  "strconv"
  "sync/atomic"
  "time"
)

type job func(in, out chan interface{})

const (
  MaxInputDataLen = 100
)

var (
  dataSignerOverheat uint32 = 0
  DataSignerSalt            = ""
)

var OverheatLock = func() {
  for {
    if swapped := atomic.CompareAndSwapUint32(&dataSignerOverheat, 0, 1); !swapped {
      fmt.Println("OverheatLock happend")
      time.Sleep(time.Second)
    } else {
      break
    }
  }
}

var OverheatUnlock = func() {
  for {
    if swapped := atomic.CompareAndSwapUint32(&dataSignerOverheat, 1, 0); !swapped {
      fmt.Println("OverheatUnlock happend")
      time.Sleep(time.Second)
    } else {
      break
    }
  }
}

var DataSignerMd5 = func(data string) string {
  OverheatLock()
  defer OverheatUnlock()
  data += DataSignerSalt
  dataHash := fmt.Sprintf("%x", md5.Sum([]byte(data)))
  time.Sleep(10 * time.Millisecond)
  return dataHash
}

var DataSignerCrc32 = func(data string) string {
  data += DataSignerSalt
  crcH := crc32.ChecksumIEEE([]byte(data))
  dataHash := strconv.FormatUint(uint64(crcH), 10)
  time.Sleep(time.Second)
  return dataHash
}


Here is a sheet
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [semacquire]:
sync.runtime_Semacquire(0xc00001a0f8)
        C:/Program Files/Go/src/runtime/sema.go:56 +0x49
sync.(*WaitGroup).Wait(0xc00001a0f0)
        C:/Program Files/Go/src/sync/waitgroup.go:130 +0x6b
main.SingleHash(0xc000018180, 0xc00002c090, 0x3, 0x3)
        C:/Users/engis/OneDrive/Рабочий стол/Go-learn-master/Go-learn-master/hw2_signer/signer.go:24 +0x1cc
main.main()
        C:/Users/engis/OneDrive/Рабочий стол/Go-learn-master/Go-learn-master/hw2_signer/signer.go:68 +0xc5

goroutine 6 [chan send]:
main.workerSingleHash(0xc00001a0f0, 0xc00001a0c8, 0xb36b68, 0x1, 0xc000018180)
        C:/Users/engis/OneDrive/Рабочий стол/Go-learn-master/Go-learn-master/hw2_signer/signer.go:45 +0x2b7
created by main.SingleHash
        C:/Users/engis/OneDrive/Рабочий стол/Go-learn-master/Go-learn-master/hw2_signer/signer.go:21 +0x1a5

goroutine 7 [chan send]:
main.workerSingleHash(0xc00001a0f0, 0xc00001a0c8, 0xb36b78, 0x1, 0xc000018180)
        C:/Users/engis/OneDrive/Рабочий стол/Go-learn-master/Go-learn-master/hw2_signer/signer.go:45 +0x2b7
created by main.SingleHash
        C:/Users/engis/OneDrive/Рабочий стол/Go-learn-master/Go-learn-master/hw2_signer/signer.go:21 +0x1a5

goroutine 8 [chan send]:
main.workerSingleHash(0xc00001a0f0, 0xc00001a0c8, 0xb36b88, 0x1, 0xc000018180)
        C:/Users/engis/OneDrive/Рабочий стол/Go-learn-master/Go-learn-master/hw2_signer/signer.go:45 +0x2b7
created by main.SingleHash
        C:/Users/engis/OneDrive/Рабочий стол/Go-learn-master/Go-learn-master/hw2_signer/signer.go:21 +0x1a5
exit status 2

Answer the question

In order to leave comments, you need to log in

1 answer(s)
D
Dmitry Shitskov, 2021-09-17
@wubbacom

I see this problem:

  1. You are creating an unbuffered done channel.
  2. Functions attempting to write to the done pipe block until the pipe is read.

I propose such a fix - in the main function, run SingleHash(done, in[1:])as a goroutine so as not to block main and proceed to waiting for a response from the done channel. And in this case, go func(done chan interface{})it will be necessary to execute synchronously, and not as a goroutine.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question