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

Corrections to timedwait methods #35103

Merged
merged 9 commits into from
Apr 7, 2020
Merged

Conversation

omus
Copy link
Member

@omus omus commented Mar 13, 2020

Mainly I wanted to update the timedwait function to be able to take Real instead of just Float64. During this process I found that the timedwait method which takes Period was missing the pollint keyword and I made some adjustments there as well.

The timedwait function currently doesn't have any tests so I'll probably also do that as part of this PR.

@omus omus added domain:dates Dates, times, and the Dates stdlib module needs tests Unit tests are required for this change labels Mar 13, 2020
@JeffBezanson
Copy link
Sponsor Member

Bump

@omus
Copy link
Member Author

omus commented Apr 1, 2020

I'll add some tests today

@omus omus force-pushed the cv/timedwait-period-poll branch from d372b20 to 70d15d4 Compare April 1, 2020 18:42
@omus
Copy link
Member Author

omus commented Apr 1, 2020

Alright, tests have now been added. One thing to note is that timedwait now rethrows exceptions raised by the callback function instead of returning :error. The rational behind this change is that if the callback function would error on the first call then an exception would be raised instead of returning :error. This approach is now consistent and should provide details as to what the exception is.

Also note I've removed the seconds function as the changes I made probably need additional discussion. A quick overview of the issue was that toms truncates units smaller than milliseconds instead of fractional number.


function Base.timedwait(testcb::Function, timeout::Period; pollint::Period=Millisecond(100))
timedwait(testcb, toms(timeout) / 1000, pollint=toms(pollint) / 1000)
end
Copy link
Member Author

@omus omus Apr 1, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll call out that toms truncates to milliseconds which means we're losing precision if a user passes in say Nanosecond(1) for either the timeout or pollint. However, since timedwait can only actually support millseconds this isn't really an issue.

This is one of those cases where two wrongs can make a right ;)

@omus omus removed the needs tests Unit tests are required for this change label Apr 1, 2020
base/asyncevent.jl Outdated Show resolved Hide resolved
@@ -284,7 +285,8 @@ function timedwait(testcb::Function, secs::Float64; pollint::Float64=0.1)

if !testcb()
t = Timer(timercb, pollint, interval = pollint)
ret = fetch(done)::Symbol
ret = fetch(done)
ret isa Exception && rethrow(ret)
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should rely on the type of e; can use a boolean flag instead.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about if we store a Tuple{Symbol, Union{Nothing, Exception}} in the channel? Then this code would look like:

ret, e = fetch(done)
ret === :error && rethrow(e)

@omus omus force-pushed the cv/timedwait-period-poll branch from 70d15d4 to 34eb22b Compare April 2, 2020 16:20
@omus
Copy link
Member Author

omus commented Apr 2, 2020

Looks like I need to increase my timing tolerance:

Test Failed at /Users/julia/buildbot/worker-tabularasa/tester_macos64/build/share/julia/test/channels.jl:268
  Expression: ≈(duration, 1, atol = 0.05)
   Evaluated: 1.182448603 ≈ 1 (atol=0.05)

@omus
Copy link
Member Author

omus commented Apr 3, 2020

Tolerance is still too small:

Test Failed at /Users/julia/buildbot/worker-tabularasa/tester_macos64/build/share/julia/test/channels.jl:265
  Expression: ≈(duration, 1, atol = 0.2)
   Evaluated: 1.229485612 ≈ 1 (atol=0.2)
Error in testset channels:
Test Failed at /Users/julia/buildbot/worker-tabularasa/tester_macos64/build/share/julia/test/channels.jl:268
  Expression: ≈(duration, 1, atol = 0.2)
   Evaluated: 1.207294196 ≈ 1 (atol=0.2)

@omus
Copy link
Member Author

omus commented Apr 3, 2020

I'm either really lucky or really unlucky:

Test Failed at /buildworker/worker/tester_linuxaarch64/build/share/julia/test/channels.jl:265
  Expression: ���(duration, 1, atol = 0.25)
   Evaluated: 1.252809605 ��� 1 (atol=0.25)
Error in testset channels:
Test Failed at /buildworker/worker/tester_linuxaarch64/build/share/julia/test/channels.jl:268
  Expression: ���(duration, 1, atol = 0.25)
   Evaluated: 1.297370699 ��� 1 (atol=0.25)

I'll go to a tolerance of 0.4

@@ -284,7 +285,8 @@ function timedwait(testcb::Function, secs::Float64; pollint::Float64=0.1)

if !testcb()
t = Timer(timercb, pollint, interval = pollint)
ret = fetch(done)::Symbol
ret, e = fetch(done)
ret === :error && rethrow(e)
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rethrow doesn't work outside a catch block (it's throwing ERROR: rethrow(exc) not allowed outside a catch block) so you have to use throw.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bad mistake on my part. Unfortunately this means that the exception thrown won't have the original stacktrace

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only if the callback raises an exception on the first call will generate the original stack trace. Exceptions raised after will not have the original stack trace. This seems better than silencing all exceptions from the callback.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively I can have timedwait return :error again and just capture exceptions from the first testcb call

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could capture the stack trace and store it in a CapturedException?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated the code to always return a CapturedException

@omus
Copy link
Member Author

omus commented Apr 6, 2020

CI failures look network related

@JeffBezanson JeffBezanson reopened this Apr 6, 2020
@omus omus force-pushed the cv/timedwait-period-poll branch from 39d4cd9 to 906f6d2 Compare April 7, 2020 19:22
@omus
Copy link
Member Author

omus commented Apr 7, 2020

Rebased changes

@JeffBezanson JeffBezanson merged commit 241947f into master Apr 7, 2020
@JeffBezanson JeffBezanson deleted the cv/timedwait-period-poll branch April 7, 2020 23:52
ztultrebor pushed a commit to ztultrebor/julia that referenced this pull request Apr 17, 2020
* Refactor methods of sleep, Timer, and timedwait

Made argument names consistent with documentation where reasonable.

* Support pollint keyword in timedwait using Periods

* Allow timedwait to take Real

* Add tests for timedwait

* Fix bug with sub-millisecond pollint

* Test timedwait with Period parameters

* Rethrow exceptions raised by timedwait callback
staticfloat pushed a commit that referenced this pull request Apr 21, 2020
* Refactor methods of sleep, Timer, and timedwait

Made argument names consistent with documentation where reasonable.

* Support pollint keyword in timedwait using Periods

* Allow timedwait to take Real

* Add tests for timedwait

* Fix bug with sub-millisecond pollint

* Test timedwait with Period parameters

* Rethrow exceptions raised by timedwait callback
@KristofferC KristofferC mentioned this pull request Apr 24, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
domain:dates Dates, times, and the Dates stdlib module
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants