Can os_unfair_lock be used with C++ interop enabled?

When os_unfair_lock_lock() is called with C++ interop enabled, it crashes with "os_unfair_lock is corrupt". When C++ interop is disabled, it works fine. I realized OSAllocatedUnfairLock exists, but this requires macOS 13. I suspect something is happening with the os_unfair_lock() call. Here's the code, based on various online examples:

import os.lock

struct Lock: ~Copyable {
    private let ptr: os_unfair_lock_t

    init() {
        self.ptr = .allocate(capacity: 1)
        self.ptr.initialize(to: os_unfair_lock())
    }

    func lock() {
        os_unfair_lock_lock(ptr)
    }

    func unlock() {
        os_unfair_lock_unlock(ptr)
    }

    deinit {
        self.ptr.deinitialize(count: 1)
        self.ptr.deallocate()
    }
}

let lock = Lock()
lock.lock()
lock.unlock()

There was a bug in C++ interop until recently which prevented calling a default Swift initializer on a C struct like os_unfair_lock_s() from zero-initializing the struct, causing it to create an uninitialized junk value instead. This has been fixed recently in the main branch, but in currently released compilers you may need to zero out the memory with memset instead to work around the bug.

7 Likes

Thanks! It looks like this is the fix:

I was able to fix by changing the initialize() call to:

var value = os_unfair_lock()
memset(&value, 0, MemoryLayout.size(ofValue: value))
self.ptr.initialize(to: value)
2 Likes