#SwiftLang #concurrency program stall question:

Given an array of urls to files the code does this:

// some prep code
await withTaskGroup { group in
var limit = min(urls.count, maxConcurrentTasks)
for ix in 0..<limit {
group.addTask { TypeInit(url: urls[ix]) }
}
for await type in group {
await doSomethingWith(type)
if limit < urls.count {
let url = urls[limit]
limit += 1
group.addTask { TypeInit(url: url }
}
}
}
// some other code never reached when the hang occurs

The issue is that when testing the code sometimes stops. No processor activity. The program is blocked waiting for something. I don't know what.

maxConcurrentTasks is currently 128 and is picked to get reasonable UI feedback. doSomethingWith(type) is not async but is on the MainActor. I've also used an explicit

await MainActor.run { doSomethingWith(type) }

No difference. (1/2)

Adding debug in the withTaskGroup code either hides the problem or doesn't help debug the cause. Adding debug elsewhere to check progress shows that the blockage occurs before all items have been processed, but never at the same spot. It is as if the `for await type…` sometime waits for a value that never appears. Note that TypeInit() is not async, but may involve file I/O or the exec of an external process.

Any hints on how to track down the possible cause? I’m tired of throwing random bits of code around hoping for a change. (2/2)

@marchyman what does “doSomethingWith” do? I bet that’s it.

@mattiem You were partially correct with your guess. It wasn't what “doSomethingWith" did, it was the fact that “doSomethingWith” was MainActor.

Taking the await out of the code inside the ‘await type in group { … }’ closure by marshaling the results and updating once when done not only seems to have fixed the hang, but also is an order of magnitude faster.

And to think I did it the first way because I wanted to give feedback to the user quicker. doh!

@marchyman hmmm do you understand why?
@mattiem For the slowdown my guess: the switch to MainActor requires a pass through the run loop limiting the updates to maybe one per cycle. For the hang I've no clue, but I suspect a race/bug somewhere in Apple's code. I have a traces where the app seems to stop for a short while then kicked off again for no reason I could detect.