Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure that content is complete using a queue #5986

Merged
merged 3 commits into from
Feb 10, 2025

Conversation

SimplyDanny
Copy link
Collaborator

The previous solution worked most of the time, but every now and then it failed due to laxly defined order.

@SwiftLintBot
Copy link

SwiftLintBot commented Feb 1, 2025

1 Warning
⚠️ If this is a user-facing change, please include a CHANGELOG entry to credit yourself!
You can find it at CHANGELOG.md.
18 Messages
📖 Building this branch resulted in a binary size of 29488.45 KiB vs 29491.24 KiB when built on main (-1% smaller).
📖 Linting Aerial with this PR took 0.92 s vs 0.93 s on main (1% faster).
📖 Linting Alamofire with this PR took 1.26 s vs 1.27 s on main (0% faster).
📖 Linting Brave with this PR took 8.46 s vs 8.48 s on main (0% faster).
📖 Linting DuckDuckGo with this PR took 5.72 s vs 5.72 s on main (0% slower).
📖 Linting Firefox with this PR took 11.56 s vs 11.59 s on main (0% faster).
📖 Linting Kickstarter with this PR took 9.99 s vs 9.98 s on main (0% slower).
📖 Linting Moya with this PR took 0.52 s vs 0.52 s on main (0% slower).
📖 Linting NetNewsWire with this PR took 2.86 s vs 2.87 s on main (0% faster).
📖 Linting Nimble with this PR took 0.78 s vs 0.78 s on main (0% slower).
📖 Linting PocketCasts with this PR took 8.68 s vs 8.73 s on main (0% faster).
📖 Linting Quick with this PR took 0.43 s vs 0.43 s on main (0% slower).
📖 Linting Realm with this PR took 4.48 s vs 4.5 s on main (0% faster).
📖 Linting Sourcery with this PR took 2.3 s vs 2.3 s on main (0% slower).
📖 Linting Swift with this PR took 4.67 s vs 4.65 s on main (0% slower).
📖 Linting VLC with this PR took 1.26 s vs 1.26 s on main (0% slower).
📖 Linting Wire with this PR took 18.28 s vs 18.34 s on main (0% faster).
📖 Linting WordPress with this PR took 11.31 s vs 11.36 s on main (0% faster).

Here's an example of your CHANGELOG entry:

* Ensure that content is complete using a queue.  
  [SimplyDanny](https://github.com/SimplyDanny)
  [#issue_number](https://github.com/realm/SwiftLint/issues/issue_number)

note: There are two invisible spaces after the entry's text.

Generated by 🚫 Danger

@OneSadCookie
Copy link
Contributor

I'm not 100% on what's going on here, but at least this is concerning:

        actor Console {
            static var content = ""
        }

This is a mutable global without a lock. Placing it in an actor is doing nothing (except possibly confusing the reader; it may as well be an enum if all you want is the ability to declare a static at function scope).

The test probably passes so long as tests don't execute concurrently, but when they do, all bets are off as to which test receives what output. Adopting Swift Testing will likely make the problem more visible?

But I also don't think you need a queue to fix the problem; simply locking around access to content should make it just as reliable as the queue. (There's still a potential issue if the runner block spawns asynchronous work that prints issues from multiple tasks, that the order of prints won't be deterministic, but that doesn't seem to be the case currently.)

It seems the project doesn't have an equivalent of OSAllocatedUnfairLock (and can't use Synchronization.Mutex) yet; it might be time to add one?

@SimplyDanny
Copy link
Collaborator Author

I got rid of the global variable. My assumption was that the actor would protect it but should have noticed that the compiler didn't require await when it was modified.

The local variable that's now used would be isolated to @MainActor, so that there are no races. Order can still be indeterministic, but that's okay.

The queue is needed to ensure all print operations to have finished before captureConsole returns the result. I'm not sure this can be guaranteed otherwise as print is non-isolated and can be called from everywhere anytime inside of runner.

I experimented with Swift Testing. However, adopting it would mean excluding people who are still on Xcode <16. That's perhaps a bit too early.

@mattmassicotte
Copy link

That's a good catch on the actor static. Those are known unsafe swiftlang/swift#78435

There might also be an issue with changing priority in that Task. It might also be possible to preserve ordering with a simple AsyncStream, if you don't want to take on another dependency.

@SimplyDanny
Copy link
Collaborator Author

It might also be possible to preserve ordering with a simple AsyncStream, if you don't want to take on another dependency.

Oh, that's great! AsyncStream works well and makes the code a bit easier, too.

@SimplyDanny SimplyDanny merged commit 82fd3e4 into realm:main Feb 10, 2025
20 checks passed
@SimplyDanny SimplyDanny deleted the print-queue branch February 10, 2025 21:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants