// Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package time import ( "errors" "runtime" ) func init() { // force US/Pacific for time zone tests ForceUSPacificForTesting() } var Interrupt = interrupt var DaysIn = daysIn func empty(now int64, arg interface{}) {} // Test that a runtimeTimer with a duration so large it overflows // does not cause other timers to hang. // // This test has to be in internal_test.go since it fiddles with // unexported data structures. func CheckRuntimeTimerOverflow() error { // We manually create a runtimeTimer to bypass the overflow // detection logic in NewTimer: we're testing the underlying // runtime.addtimer function. r := &runtimeTimer{ when: nano() + (1<<63 - 1), f: empty, arg: nil, } startTimer(r) timeout := 100 * Millisecond if runtime.GOOS == "windows" { // Allow more time for gobuilder to succeed. timeout = Second } // Start a goroutine that should send on t.C before the timeout. t := NewTimer(1) defer func() { // Subsequent tests won't work correctly if we don't stop the // overflow timer and kick the timer proc back into service. // // The timer proc is now sleeping and can only be awoken by // adding a timer to the *beginning* of the heap. We can't // wake it up by calling NewTimer since other tests may have // left timers running that should have expired before ours. // Instead we zero the overflow timer duration and start it // once more. stopTimer(r) t.Stop() r.when = 0 startTimer(r) }() // Try to receive from t.C before the timeout. It will succeed // iff the previous sleep was able to finish. We're forced to // spin and yield after trying to receive since we can't start // any more timers (they might hang due to the same bug we're // now testing). stop := Now().Add(timeout) for { select { case <-t.C: return nil // It worked! default: if Now().After(stop) { return errors.New("runtime timer stuck: overflow in addtimer") } runtime.Gosched() } } }