-
Notifications
You must be signed in to change notification settings - Fork 266
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
Sr 1872 using runloopsource in wait for expectation #314
base: main
Are you sure you want to change the base?
Sr 1872 using runloopsource in wait for expectation #314
Conversation
@compnerd can we test the changes?? |
@swift-ci please test |
Previous discussions: #304 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @pranavshenoy, thanks for taking this on. I have familiarized myself with the discussion on the previous PR, #304, and I have a few questions. One "larger" question, and some smaller inline suggestions about the code…
My biggest question about this change is: Is it missing the step of "signaling" the run loop source? I had to refresh my memory on how these work, but IIRC the idea behind run loop sources is that, once you assign a source to a run loop and begin running the run loop, it begins and doesn't finish until either its source is signaled or it times out.
In this PR, it looks like you're adding the source to the run loop, and at the very end (once it's no longer needed) you're calling invalidate()
on the source… but I don't see a place where RunLoop._Source.signal()
is called. My understanding was that, each time one of the waiter's XCTestExpectations is fulfilled, we would need to signal()
the source to cause the run loop to spin again. And looking at Apple's documentation for CFRunLoopSourceSignal
(the underlying C API), it seems like one would need to call CFRunLoopWakeUp
after signal()
as well, since we'd want the run loop to process it and fire immediately. (I'm not sure there's a Swift RunLoop._Source
wrapper for CFRunLoopWakeUp
, yet.)
Can you clarify if I am misunderstanding something or if this signaling happens a different way?
@@ -405,7 +389,7 @@ extension XCTWaiter: ManageableWaiter { | |||
dispatchPrecondition(condition: .onQueue(XCTWaiter.subsystemQueue)) | |||
|
|||
queue_validateExpectationFulfillment(dueToTimeout: true) | |||
manager!.queue_handleWatchdogTimeout(of: self) | |||
manager?.queue_handleWatchdogTimeout(of: self) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What was the reason for changing this, did you encounter a case where the force-unwrap failed after your changes? I vaguely recall using force unwrap intentionally here to represent the expectation that, at this point in the waiter lifecycle, it definitely should still have a WaiterManager, but I may have missed something or this PR could have changed that invariant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Initially, this was causing crashes. Hence, felt optional unwrapping would be safer to avoid crashes.
Have reverted the changes. Thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@stmontgomery was looking into the root cause of the crash. It looks like for the scenario where the duration of wait() is less than or equal to zero (there are two functional test cases for this), there exists a race-condition between queue_handleWatchdogTimeout()
and self.manager = nil
with the latest changes. This is because the isFinished
property, which has subsystemQueue.sync
that prevents the race-condition, is not needed in the latest changes.
Please let me know if the approach needs to be changed.
@@ -117,7 +117,7 @@ open class XCTWaiter { | |||
internal var waitSourceLocation: SourceLocation? | |||
private weak var manager: WaiterManager<XCTWaiter>? | |||
private var runLoop: RunLoop? | |||
|
|||
private var runLoopSource: RunLoop._Source? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I notice the RunLoop._Source
type and several of its related RunLoop methods are marked as deprecated in Foundation… does that mean this PR will introduce new build warnings to the XCTest codebase? I wonder what we can do about that, since Swift has no way to "silence" those warnings.
Hi @stmontgomery From my understanding of the code, the RunLoop in the From my understanding of the task, the while loop in the Please let me know if I am misinterpreting the code and/or the task. |
4b7289d
to
9b64c4a
Compare
9b64c4a
to
34c57d1
Compare
@compnerd could you please trigger the build? Thanks |
@swift-ci test |
@stmontgomery I tried it out locally and all tests were successful. Could you please tell me if there is some gap with this approach that I am missing? If this one is good, I can proceed and make the necessary changes. Thanks |
@stmontgomery @millenomi Can you share your thoughts on this? |
@stmontgomery @millenomi @compnerd Could you please provide your inputs on this? Thanks |
@stmontgomery @millenomi @compnerd Could you please provide your inputs on this? |
SR-1872 Replacing polling expectations to check whether an expectation is fulfilled with RunloopSource