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

runtime: use monotonic time on netbsd #6007

Closed
gopherbot opened this issue Aug 1, 2013 · 46 comments
Closed

runtime: use monotonic time on netbsd #6007

gopherbot opened this issue Aug 1, 2013 · 46 comments
Labels
FrozenDueToAge OS-NetBSD Suggested Issues that may be good for new contributors looking for work to do.
Milestone

Comments

@gopherbot
Copy link
Contributor

by gmale120:

import (

    "fmt"

    "time"

)


func main() {

    go aa()

    var str string

    fmt.Scan(&str)

}

func aa() {

    var t time.Time

    for {

        x := time.After(5 * time.Second)

        t = <-x

        fmt.Println(t)

    }


}
如果我改变了系统的当前时间,然后这个就失效了。
我先把当前时间提前一小时,看有没有输入。等了很久,没有输出。
然后再改回来,还是没有输出。
就算你出问题,也别死在那里呀
不准没关系。失效问题就大了
Automatic translation 

If I change the system's current time, then this failure. 

I change the system's time befor current time. Wait for a long time, no output. 

And then change back,and wait a moment,still no output. 

There, even when you are out of the question, don't also died 

No it doesn't matter. Failure problem is big
@rsc
Copy link
Contributor

rsc commented Aug 2, 2013

Comment 1:

What operating system are you using?
This may be a problem in the way we are using the system timers but it may also just be
a problem with the OS.

Labels changed: added priority-later, suggested, removed priority-triage.

Status changed to Accepted.

@alexbrainman
Copy link
Member

Comment 2:

The output surely stops (on both linux and windows) if I change my system time to minute
late. :-)
Alex

@rsc
Copy link
Contributor

rsc commented Sep 9, 2013

Comment 3:

Status changed to TimedOut.

@alexbrainman
Copy link
Member

Comment 4:

Russ, why did you set status to "TimedOut"? I think there is a problem here. It just a
question whether we want / can fix it. Or if it is important enough. Isn't it?
Alex

@rsc
Copy link
Contributor

rsc commented Sep 9, 2013

Comment 5:

Can you post an example program and explain how to demonstrate the problem? I closed the
issue because I don't understand the report.

Status changed to WaitingForReply.

@alexbrainman
Copy link
Member

Comment 6:

Run this program
package main
import (
        "fmt"
        "time"
)
func main() {
        for {
                fmt.Println(<-time.After(time.Second))
        }
}
and watch it outputs new line to stdout once every second. While the program runs,
change your system time to 1 minute back (whatever your current time is minus 1 minute).
I use "date" command on linux for that. Watch running program output stops. Should it?
Shouldn't it?
Alex

@karalabe
Copy link
Contributor

Comment 7:

Hi,
  Here's a go-nuts thread about this exact same issue that hit me in the face yesterday: https://groups.google.com/forum/#!topic/golang-nuts/mUOr4UvsYOY
  The issue is that any pending ticker will get ruined during an OS time update. E.g. as in the above examples, you start a ticker for 1 secs, set back the OS timer a few hours, and the ticker will never fire (at least not until the OS time reaches the original ticker time).
  And to give you two real-world examples when this happens: daylight saving (OS updates the date, all tickers pause for an hour). The other is what I got hit with: you boot up the OS, automatically start a Go program, and after a while the clock syncs up and all tickers within the program get corrupted (and this is what actually happens on Google Compute Engine VMs).
Cheers,
  Peter

@dvyukov
Copy link
Member

dvyukov commented Sep 13, 2013

Comment 8:

The issues in #7 looks WorksAsExpected/Unfortunate, because time operates with real time
FWIW. Which is, in my opinion, a design bug, but it is the way it is. This should be
solved as part of a more serious changes, there is a discussion on goleng-dev about
monotonic clocks.
Is it the case that when you set time a minute back, timers stop ticking at all (no
ticks after 5 minutes)? This would be a bug.

@alexbrainman
Copy link
Member

Comment 9:

> Is it the case that when you set time a minute back, timers stop ticking at all (no
ticks after 5 minutes)?
No, it is not the case. Timer starts ticking again once new time catchers up with old
time. The program is stuck for 1 minute and then it continues on as if nothing happend.
Alex

@rsc
Copy link
Contributor

rsc commented Sep 15, 2013

Comment 10:

There's no magic bullet here. If we use wall time we get weirdness like this when the
computer's reported wall time jumps around. If we use some other kind of monotonic "time
since boot" time, then things like:
t := time.Now()
time.Sleep(10*time.Minute)
fmt.Println(time.Since(t))
can literally print any value, something arbitrarily far from 10 minutes, even a
negative number.
I don't think there's anything we can do here that is significantly better than what we
have.

Status changed to Unfortunate.

@jayschwa
Copy link
Contributor

Comment 11:

This same issue (wall clock vs monotonic clock) caused real problems at my previous
embedded systems job (using C, not Go :-). I think it's a serious issue and should not
be taken lightly.
Currently, it looks like nanotime() and now() are aliases to each other. My armchair
layman's thought is to keep now() functionally the same (i.e. it returns wall time) and
have nanotime() use a monotonic clock instead. I'd try it myself except that the
relevant bits are in assembly and I haven't wrapped my head around it yet.
Considering two core devs have called this issue "Unfortunate", I must be missing
something though.

@dvyukov
Copy link
Member

dvyukov commented Sep 15, 2013

Comment 12:

I meant that is's more WorksAsExpected, because it's the current documented semantics,
we can not just change it.
However, there are things we can do about it. If you want to blink a window every
second, check email every minute, or timeout idle tcp connection after 5 min, then you
pretty much do not care about the output of:
t := time.Now()
time.Sleep(10*time.Minute)
fmt.Println(time.Since(t))
You just want timers against monotonic time.
In the end, the following code can work perfectly reasonably (well, hibernation aside):
t := time.MonoNow()
time.MonoSleep(10*time.Minute)
fmt.Println(time.MonoSince(t))
Currently we do strange wtfs like timing out tcp connections based on real time...

@rsc
Copy link
Contributor

rsc commented Sep 15, 2013

Comment 13:

It may be possible to make all the relative APIs - After, Sleep, Tick,
Ticker, and Timer - use durations against 'monotonic time'. The package net
timeouts could do the same internally. However, neither will happen for Go
1.2.
The real WTF here is that there are still systems that cannot keep accurate
time and have giant backward or forward time jumps in their real time. Come
on, guys. It's 2013.

Labels changed: added go1.3, removed go1.2maybe.

Status changed to Thinking.

@dvyukov
Copy link
Member

dvyukov commented Sep 15, 2013

Comment 14:

> The real WTF here is that there are still systems that cannot keep accurate time and
have giant backward or forward time jumps in their real time.
This is not an issue. It is the same on good OSes as well.
If you came from server land, you can think that real time==monotonic time. But this is
absolutely not true in desktop environment (and there are still bad administrators and
so on). On the golang-dev thread I've described some examples when real time changes
+/-24h several times a day. For some period of time I was periodically changing real
time on my desktop +/-3 *years* to trick some software.
Do NOT think of real time as of something related to monotonic time whatever OS you
have. For the purpose of correctness, real time must be considered as random number
generator.
This is expected that if you want to schedule some activity every (realtime) midnight,
it will behave weirdly in such environment (and there is nothing we can do with it).
But it's a failure on our side, if all Go software suddenly crashes/timeouts/hangs when
a user changes real time to +/-12h. And this is what happens now (all network
connections suddenly timeout or never timeout; time.Ticker(time.Second) stops ticking,
etc).

@jayschwa
Copy link
Contributor

Comment 15:

> it's the current documented semantics, we can not just change it.
Where is it documented? I do not see anything in the documentation for Duration (or the
functions that use it) that indicates it is used as a delta for wall time. If anything,
I think changing Duration-related functions to use a monotonic clock would make it more
accurate and less surprising with its current documentation.
> The real WTF here is that there are still systems that cannot keep accurate
time and have giant backward or forward time jumps in their real time.
Not all devices have the luxury of saving the time and asking the Internet. At my
previous job, I worked on an embedded system that did not save time across power cycles
because it was small and didn't have a battery. An external source would eventually push
a time to my device sometime after boot. The time updates would not necessarily come
right away, and sometimes the time would jump around multiple times (and by large
magnitudes) depending on the kind of testing the systems guys were doing. The software
had to use monotonic clocks in order to be robust and not break during wall time changes.

@dvyukov
Copy link
Member

dvyukov commented Sep 15, 2013

Comment 16:

> Where is it documented?
I have not looked at the documentation, but:
1. it is how it works now, so people may be relying on it (even if it's not explicitly
documented).
2. Go does not have a notion of monotonic time, so it's reasonable to infer that
everything relates to real time. E.g. Russ's example in #10 should print something close
to 10min, rather than arbitrary value.
Probably we may try to change it, but we must be very careful.
To make it clear, I agree that it's not for Go1.2. This requires very serious changes.
On second though (I think I already described it in the golang-dev thread),
time.Sleep(10*time.Minute) can not possibly reliably sleep till some real time instant
(e.g. midnight). A function that sleeps till some real time instant must necessary
accept time instant (i.e. time.Time), otherwise it's broken if time change happens
before runtime converts time.Duration to time.Time.
So, Russ, your example in #10 prints random value even now. And of course time can be
changes after time.Sleep returns, but before you query time.Now the second time.
>The software had to use monotonic clocks in order to be robust and not break during
wall time changes.
This is a good idea in all other contexts as well.

@rsc
Copy link
Contributor

rsc commented Dec 4, 2013

Comment 17:

Labels changed: added release-go1.3, removed go1.3.

@rsc
Copy link
Contributor

rsc commented Dec 4, 2013

Comment 18:

Labels changed: added repo-main.

@jayschwa
Copy link
Contributor

Comment 19:

I've created a naive fix for linux_amd64. I can now run the snippet from comment #6 and
the program won't lose its marbles after changing the host's calendar time. The changes
are small enough that they'll hopefully be self-explanatory. I wrote what I thought was
the simplest way - not necessarily the best way - just to get others thinking about it.

@jayschwa
Copy link
Contributor

Comment 20:

I suppose a link to the changes would help:
https://github.com/jayschwa/golang/compare/master...monotonic

@balasanjay
Copy link
Contributor

Comment 21:

rsc: to add on to what dvyukov said in #14, there is a very common case where this
happens all the time. Specifically, if you put your phone/laptop in airplane mode, then
get on a plane, and fly far enough. When you land and resync your clock, it can jump
around quite significantly.
I once had a user file a bug report on an iOS app with this exact issue.

@davecheney
Copy link
Contributor

Comment 22:

@21, was this because the user was in the air for so long that it was no longer possible
to slew the clock?

@dvyukov
Copy link
Member

dvyukov commented Jan 25, 2014

Comment 23:

There is https://golang.org/cl/53010043/ in progress

@rsc
Copy link
Contributor

rsc commented Feb 24, 2014

Comment 24:

This issue was updated by revision 86c976f.

LGTM=dvyukov, rsc
R=golang-codereviews, dvyukov, alex.brainman, stephen.gutekanst, dave, rsc, mikioh.mikioh
CC=golang-codereviews
https://golang.org/cl/53010043
Committer: Russ Cox 

@jayschwa
Copy link
Contributor

Comment 25:

The recent commit takes care of linux 386 and amd64. The implementations of
runtime.nanotime() for the other platforms (darwin, windows, bsd, etc) still need
updates.

@mikioh
Copy link
Contributor

mikioh commented Feb 25, 2014

Comment 26:

This issue was updated by revision 7206f50.

LGTM=dvyukov
R=golang-codereviews, dvyukov
CC=golang-codereviews
https://golang.org/cl/67730048

@mikioh
Copy link
Contributor

mikioh commented Feb 26, 2014

Comment 27:

This issue was updated by revision 36013e4.

LGTM=minux.ma
R=golang-codereviews, minux.ma, bradfitz
CC=golang-codereviews
https://golang.org/cl/68690043

@4a6f656c
Copy link
Contributor

Comment 28:

This issue was updated by revision 3734663.

LGTM=bradfitz
R=golang-codereviews, bradfitz
CC=golang-codereviews
https://golang.org/cl/68460044

@minux
Copy link
Member

minux commented Feb 27, 2014

Comment 29:

This issue was updated by revision b4dc91e.

LGTM=bradfitz
R=golang-codereviews, bradfitz
CC=golang-codereviews
https://golang.org/cl/69040045

@rsc
Copy link
Contributor

rsc commented Apr 3, 2014

Comment 30:

I see monotonic timers for Linux, FreeBSD, OpenBSD, and DragonflyBSD. I don't see a
monotonic clock on OS X.
That leaves Windows and NetBSD, right?

Labels changed: added release-go1.3maybe, removed release-go1.3.

Status changed to Accepted.

@dvyukov
Copy link
Member

dvyukov commented Jul 15, 2014

Comment 40:

Go dumps system time precision to 1ms, so it's not that bad.

@dvyukov
Copy link
Member

dvyukov commented Jul 15, 2014

Comment 41:

Go bumps system time precision to 1ms, so it's not that bad.

@alexbrainman
Copy link
Member

Comment 42:

Jayschwa, thanks for the link. I ill have a look.
Alex

@gopherbot
Copy link
Contributor Author

Comment 43:

CL https://golang.org/cl/108700045 mentions this issue.

@gopherbot gopherbot added accepted Suggested Issues that may be good for new contributors looking for work to do. labels Jul 16, 2014
@jayschwa
Copy link
Contributor

Windows can be removed from the issue title. It was implemented in 74b62b4.

@bradfitz bradfitz changed the title time: use monotonic time on netbsd, windows time: use monotonic time on netbsd Dec 10, 2014
@rsc rsc added this to the Unplanned milestone Apr 10, 2015
@bradfitz bradfitz changed the title time: use monotonic time on netbsd runtime: use monotonic time on netbsd Dec 28, 2016
@gopherbot
Copy link
Contributor Author

Change https://golang.org/cl/81135 mentions this issue: runtime: use monotonic time on NetBSD

@gopherbot
Copy link
Contributor Author

Change https://golang.org/cl/81715 mentions this issue: runtime: make NetBSD lwp_park use monotonic time

gopherbot pushed a commit that referenced this issue Dec 4, 2017
This change updates runtime.semasleep to no longer call
runtime.nanotime and instead calls lwp_park with a duration to sleep
relative to the monotonic clock, so the nanotime is never called.
(This requires updating to a newer version of the lwp_park system
call, which is safe, because Go 1.10 will require the unreleased
NetBSD 8+ anyway)

Additionally, this change makes the nanotime function use the
monotonic clock for netbsd/arm, which was forgotten from
https://golang.org/cl/81135 which updated netbsd/amd64 and netbsd/386.

Because semasleep previously depended on nanotime, the past few days
of netbsd have likely been unstable because lwp_park was then mixing
the monotonic and wall clocks. After this CL, lwp_park no longer
depends on nanotime.

Original patch submitted at:
https://www.netbsd.org/~christos/go-lwp-park-clock-monotonic.diff

This commit message (any any mistakes therein) were written by Brad
Fitzpatrick. (Brad migrated the patch to Gerrit and checked CLAs)

Updates #6007
Fixes #22968

Also updates netbsd/arm to use monotonic time for

Change-Id: If77ef7dc610b3025831d84cdfadfbbba2c52acb2
Reviewed-on: https://go-review.googlesource.com/81715
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
wheatman pushed a commit to wheatman/go-akaros that referenced this issue Jun 25, 2018
Update golang#6007.

LGTM=minux, dvyukov
R=golang-codereviews, dvyukov, patrick, aram.h, minux
CC=golang-codereviews
https://golang.org/cl/108700045
wheatman pushed a commit to wheatman/go-akaros that referenced this issue Jul 9, 2018
Update golang#6007.

LGTM=minux, dvyukov
R=golang-codereviews, dvyukov, patrick, aram.h, minux
CC=golang-codereviews
https://golang.org/cl/108700045
@golang golang locked and limited conversation to collaborators Dec 4, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge OS-NetBSD Suggested Issues that may be good for new contributors looking for work to do.
Projects
None yet
Development

No branches or pull requests