apple / swift-corelibs-libdispatch

The libdispatch Project, (a.k.a. Grand Central Dispatch), for concurrency on multicore hardware

Home Page:swift.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[SR-10119] malloc double free when using SIMD with GCD

swift-ci opened this issue · comments

Previous ID SR-10119
Radar None
Original Reporter damiaan (JIRA User)
Type Bug
Status Resolved
Resolution Done
Environment

Computer ** MacBook Pro (Retina, 15-inch, Late 2013)

OS macOS Mojave 10.14.3 (18D109)

Xcode Version 10.2 beta 4 (10P107d)

Additional Detail from JIRA
Votes 0
Component/s libdispatch, Standard Library
Labels Bug
Assignee None
Priority Medium

md5: 10714eca08e38af06d82d157ff8d93f2

Issue Description:

I am stumbling upon an issue with concurrency and SIMD in Swift 5. To reproduce the issue I have simplified my code to the following problem:

  • Initialise an array called `pixels`

  • add async tasks to a concurrent queue

  • in each task: fill a different non overlapping part of the `pixels` array

import Dispatch

let group = DispatchGroup()
let queue = DispatchQueue(
  label: "Concurrent threads",
  qos: .userInitiated,
  attributes: .concurrent
)

let threadCount = 4
let size = 1_000
var pixels = [SIMD3<Float>](
  repeating: .init(repeating: 0),
  count: threadCount*size
)
for thread in 0..<threadCount {
  queue.async(group: group) {
    for number in thread*size ..< (thread+1)*size {
      let floating = Float(number)
      pixels[number] = SIMD3<Float>(floating, floating, floating)
    }
  }
}

print("waiting")
group.wait()
print("Finished")

Executing this using Xcode 10.2 beta 4 in debug mode gives the following error:

Multithread(15936,0x700006447000) malloc: double free for ptr 0x10301b800
Multithread(15936,0x700006447000) malloc: *** set a breakpoint in malloc_error_break to debug
Program ended with exit code: 9

When I build the same program in release mode though, it runs fine and finishes correctly.

Comment by Damiaan Dufaux (JIRA)

It turned out I had to use an unsafe mutable buffer pointer like this:

pixels.withUnsafeMutableBufferPointer { pixelsPtr in
    for thread in 0..<threadCount {
        queue.async(group: group) { [pixelsPtr] in
            for number in thread*size ..< (thread+1)*size {
                let floating = Float(number)
                pixelsPtr[number] = SIMD3(floating, floating, floating)
            }
        }
    }
}

Thanks to Rob Napier for clearing this out on stack overflow