Skip to content

Commit

Permalink
fix: prevent goroutine panic in history command
Browse files Browse the repository at this point in the history
Improve channel and goroutine synchronization by:
- Moving channel closures after WaitGroup completion
- Adding safe channel sends with select statements
- Fixing nested goroutine tracking
  • Loading branch information
AccursedGalaxy committed Dec 30, 2024
1 parent 9d49849 commit ef860de
Showing 1 changed file with 18 additions and 8 deletions.
26 changes: 18 additions & 8 deletions cmd/history.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,6 @@ func DisplayHistory(opts HistoryOptions) {
}

func loadCommitsProgressively(opts HistoryOptions, commitChan chan<- CommitSummary, doneChan chan<- bool) {
defer close(commitChan)
defer close(doneChan)

var wg sync.WaitGroup
since := time.Now().AddDate(0, 0, -opts.Days)

Expand All @@ -89,24 +86,29 @@ func loadCommitsProgressively(opts HistoryOptions, commitChan chan<- CommitSumma
}

wg.Add(1)
sem <- struct{}{} // Acquire semaphore
go func(repoPath string) {
defer wg.Done()
sem <- struct{}{} // Acquire semaphore
defer func() { <-sem }() // Release semaphore

repoName := extractRepoName(repoPath)

// Get local commits first (faster)
localCommits := getLocalCommitsOptimized(repoPath, opts, since)
for _, commit := range localCommits {
commit.Repository = repoName
commitChan <- commit
select {
case commitChan <- commit:
default:
// Channel might be closed, skip
return
}
}

// Only fetch remote data if needed and not too many local commits
if len(localCommits) < 100 && shouldFetchRemote(repoPath) {
// Fetch remote data in background
wg.Add(1)
go func() {
defer wg.Done()
fetchRemoteData(repoPath)
remoteCommits := getRemoteCommitsOptimized(repoPath, opts, since)
// Only send remote commits that aren't in local
Expand All @@ -117,7 +119,12 @@ func loadCommitsProgressively(opts HistoryOptions, commitChan chan<- CommitSumma
for _, commit := range remoteCommits {
if !seenHashes[commit.Hash] {
commit.Repository = repoName
commitChan <- commit
select {
case commitChan <- commit:
default:
// Channel might be closed, skip
return
}
}
}
}()
Expand All @@ -126,8 +133,11 @@ func loadCommitsProgressively(opts HistoryOptions, commitChan chan<- CommitSumma
return true
})

// Wait for all goroutines to complete before closing channels
wg.Wait()
doneChan <- true
close(commitChan)
close(doneChan)
}

func getCachedCommits(opts HistoryOptions, since time.Time) []CommitSummary {
Expand Down

0 comments on commit ef860de

Please sign in to comment.