I fixed a few of the wait group calls, here are the problems I noticed.
tl;dr
There may just be a fundamental misunderstanding of wait groups here, the general idea is that wait groups are meant to synchronize the lifetimes of go-routines, they should not be coupled with, or coordinate values on channels which is how they're currently being used.
You were incrementing the wait group for every iteration of the for loop here, even though you weren't spawning any go-routines. You were calling wg.Done
once at the end.
go func() {
for i := *argPortStart; i <= *argPortEnd; i++ {
targetHost := fmt.Sprintf("%s:%d", *argHost, i)
wg.Add(1)
portsChan <- targetHost
}
wg.Done()
close(portsChan)
}()
I changed it to this
wg.Add(1)
go func() {
defer wg.Done()
for i := *argPortStart; i <= *argPortEnd; i++ {
targetHost := fmt.Sprintf("%s:%d", *argHost, i)
portsChan <- targetHost
}
close(portsChan)
}()
In the following snippet, you were spawning go-routines that you wanted to wait for, but you were not incrementing the wait-group. Instead, you were calling wg.Done
for each value in the channel.
// Consuming events
for i := 0; i <= *argThreadsNum; i++ {
go portScanner(portsChan, resChan, &wg)
}
I changed it to this
for i := 0; i <= *argThreadsNum; i++ {
wg.Add(1)
go portScanner(portsChan, resChan, &wg)
}
// ...
func portScanner(portsChan, resChan chan string, wg *sync.WaitGroup) {
defer wg.Done()
for targetHost := range portsChan {
_, err := net.DialTimeout("tcp", targetHost, time.Millisecond*300)
if err == nil {
resChan <- targetHost
}
}
}
There may just be a fundamental misunderstanding of wait groups here, the general idea is that wait groups are meant to synchronize the lifetimes of go-routines, they should not be coupled with values on channels.