swiftlang/swift

Cannot use Glibc.stdout/stderr with Concurrency (error: reference to var 'stderr' is not concurrency-safe because it involves shared mutable state)

Opened this issue · 6 comments

Description

Getting a compiler error when using Glibc.stdout/stderr with Concurrency

error: reference to var 'stderr' is not concurrency-safe because it involves shared mutable state

Reproduction

import Glibc
Task { fputs("hello", stderr) }

Expected behavior

compiles fine

Environment

6.0.2

Additional information

No response

nerzh commented

any updates ?

ubuntu swift 6.0.3

// GlibC Linux platforms
import Glibc 

private let stdoutLock = NSLock()

nonisolated(unsafe)
func configureStdout() {
    stdoutLock.lock()
    defer { stdoutLock.unlock() }
    setbuf(stdout, nil)
}
configureStdout()

I've tried everything, nothing works

error: reference to var 'stdout' is not concurrency-safe because it involves shared mutable state

@nerzh For now, use

@preconcurrency import Glibc

and it'll work just fine

nerzh commented

@weissi thank you for fast answer 🤝

@nerzh For now, use

@preconcurrency import Glibc

and it'll work just fine

I suspect I'm missing something, but switching adding @preconcurrency doesn't seem to be working for me:

#if os(Linux)
    @preconcurrency import Glibc
#else
    import Darwin.C
#endif

This still leaves me with:

58:20: error: reference to var 'stdout' is not concurrency-safe because it involves shared mutable state
56 |             print("\r\(message): \(percentage)% (\(progress.completedUnitCount) / \(progress.totalUnitCount))",
57 |                   terminator: "")
58 |             fflush(stdout)
   |                    `- error: reference to var 'stdout' is not concurrency-safe because it involves shared mutable state
59 |         }
60 |     }

Which is a little confusing. I imagine I'm holding it wrong.

@jbmorley Well hello friend! Are you maybe also import Foundation or something else? The @preconcurrency import Glibc needs to come before anything else is importing Glibc without @preconcurrency.

See some issues/PRs here:

Essentially, you need to put @preconcurrency import Glibc (and similar) as the very first import in all your files that require it to make sure it gets imported first with @preconcurrency. Needless to say this is silly and needs fixing in Swift.

@weissi Hi! 👋🏻

Thanks for taking the time to give me some more thoughts. Turns out I was indeed also importing Foundation. I'd put the Glibc import above everything else just in case, but at no point did it occur to me that Foundation would also be importing Glibc. Of course it is. 🤦🏻

Oh well. All working now! Thank you again.