crash after clock reset

Bug #1028026 reported by pipping on 2012-07-23
36
This bug affects 7 people
Affects Status Importance Assigned to Milestone
SBCL
Medium
Unassigned

Bug Description

As already mentioned here: https://github.com/sabetts/stumpwm/issues/7#issuecomment-7091478 (albeit not by me), the following procedure will make sbcl 1.0.57 crash:

  1. run (get-internal-real-time) in sbcl (keep sbcl running).
  2. turn the clock back an hour.
  3. call (get-internal-real-time) again.

nixie (onixie) wrote :

It seems like there are some type error that causes debugger run into a loop.
After --disable-debugger I got the following error messages and backtrace.

* unhandled TYPE-ERROR in thread #<SB-THREAD:THREAD "main thread" RUNNING
                                  {1002971023}>:
  The value -1960034 is not of type UNSIGNED-BYTE.

0: (SB-DEBUG::MAP-BACKTRACE
    #<CLOSURE (LAMBDA # :IN BACKTRACE) {1003E21DDB}>
    :START
    0
    :COUNT
    128)
1: (BACKTRACE 128 #<SYNONYM-STREAM :SYMBOL SB-SYS:*STDERR* {1000169AE3}>)
2: (SB-DEBUG::DEBUGGER-DISABLED-HOOK
    #<TYPE-ERROR expected-type: UNSIGNED-BYTE datum: -1960034>
    #<unavailable argument>)
3: (SB-DEBUG::RUN-HOOK
    *INVOKE-DEBUGGER-HOOK*
    #<TYPE-ERROR expected-type: UNSIGNED-BYTE datum: -1960034>)
4: (INVOKE-DEBUGGER #<TYPE-ERROR expected-type: UNSIGNED-BYTE datum: -1960034>)
5: (ERROR TYPE-ERROR :DATUM -1960034 :EXPECTED-TYPE UNSIGNED-BYTE)
6: (SB-KERNEL::OBJECT-NOT-TYPE-ERROR-HANDLER
    #<unavailable argument>
    #.(SB-SYS:INT-SAP #X7FFFF6CDF1A0)
    #<SB-ALIEN-INTERNALS:ALIEN-VALUE :SAP #X7FFFF6CDEB80 :TYPE (*
                                                                (STRUCT
                                                                 SB-VM::OS-CONTEXT-T-STRUCT))>
    (84 21))
7: (SB-KERNEL:INTERNAL-ERROR
    #.(SB-SYS:INT-SAP #X7FFFF6CDEB80)
    #<unavailable argument>)
8: ("foreign function: call_into_lisp")
9: ("foreign function: funcall2")
10: ("foreign function: interrupt_internal_error")
11: ("foreign function: handle_trap")
12: ("foreign function: #x412C33")
13: (GET-INTERNAL-REAL-TIME)
14: (SB-SYS:DECODE-TIMEOUT NIL)
15: (SB-SYS:WAIT-UNTIL-FD-USABLE 0 :INPUT NIL T)
16: (SB-IMPL::REFILL-INPUT-BUFFER
     #<SB-SYS:FD-STREAM for "standard input" {10029713B3}>)
17: (SB-IMPL::INPUT-CHAR/UTF-8
     #<SB-SYS:FD-STREAM for "standard input" {10029713B3}>
     NIL
     #:EOF-OBJECT)
18: ((LAMBDA (&REST REST) :IN SB-IMPL::GET-EXTERNAL-FORMAT)
     #<SB-SYS:FD-STREAM for "standard input" {10029713B3}>
     NIL
     #:EOF-OBJECT)
19: (READ-CHAR
     #<SB-SYS:FD-STREAM for "standard input" {10029713B3}>
     NIL
     #:EOF-OBJECT
     #<unused argument>)
20: (READ-CHAR
     #<SYNONYM-STREAM :SYMBOL SB-SYS:*STDIN* {10001B3173}>
     NIL
     #:EOF-OBJECT
     #<unused argument>)
21: (SB-IMPL::%READ-PRESERVING-WHITESPACE
     #<SYNONYM-STREAM :SYMBOL SB-SYS:*STDIN* {10001B3173}>
     NIL
     (NIL)
     T)
22: (SB-IMPL::%READ-PRESERVING-WHITESPACE
     #<SYNONYM-STREAM :SYMBOL SB-SYS:*STDIN* {10001B3173}>
     NIL
     (NIL)
     NIL)
23: (READ #<SYNONYM-STREAM :SYMBOL SB-SYS:*STDIN* {10001B3173}> NIL (NIL) NIL)
24: (SB-IMPL::REPL-READ-FORM-FUN
     #<SYNONYM-STREAM :SYMBOL SB-SYS:*STDIN* {10001B3173}>
     #<unavailable argument>)
25: (SB-IMPL::REPL-FUN NIL)
26: ((LAMBDA () :IN SB-IMPL::TOPLEVEL-REPL))
27: (SB-IMPL::%WITH-REBOUND-IO-SYNTAX
     #<CLOSURE (LAMBDA # :IN SB-IMPL::TOPLEVEL-REPL) {1003E1248B}>)
28: (SB-IMPL::TOPLEVEL-REPL NIL)
29: (SB-IMPL::TOPLEVEL-INIT)
30: ((FLET #:WITHOUT-INTERRUPTS-BODY-237819 :IN SAVE-LISP-AND-DIE))
31: ((LABELS SB-IMPL::RESTART-LISP :IN SAVE-LISP-AND-DIE))

unhandled condition in --disable-debugger mode, quitting

nixie (onixie) wrote :

The type error happens in function GET-INTERNAL-REAL-TIME

The value of 'now' variable is declared as unsigned-byte (which according to CLHS I think this is appropriate),
but when calculating its new value, the result from subtracting seconds might be negative one. (if setting the system time to the past).

I create a patch of this fix.
Thanks for the review and advice. :)

From 84a1161018bec29e50bca2806fdc35be93fe8249 Mon Sep 17 00:00:00 2001
From: Nixie <email address hidden>
Date: Fri, 27 Jul 2012 07:11:11 +0800
Subject: [PATCH] Rejuvenate the internal real time in case we return to the past

Fixes lp#1028026
---
 src/code/unix.lisp | 18 +++++++++++-------
 1 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/src/code/unix.lisp b/src/code/unix.lisp
index 7a1a628..fbc679a 100644
--- a/src/code/unix.lisp
+++ b/src/code/unix.lisp
@@ -1174,13 +1174,17 @@ the UNIX epoch (January 1st 1970.)"
     ;; --MG
     (defun get-internal-real-time ()
       (multiple-value-bind (sec msec) (system-real-time-values)
- (unless (and (= msec c-msec) (= sec c-sec))
- (setf now (+ (* (- sec e-sec)
- sb!xc:internal-time-units-per-second)
- (- msec e-msec))
- c-msec msec
- c-sec sec))
- now)))
+ (if (or (< sec e-sec)
+ (and (= sec e-sec) (< msec e-msec)))
+ (progn (reinit-internal-real-time)
+ (setf now 0))
+ (unless (and (= msec c-msec) (= sec c-sec))
+ (setf now (+ (* (- sec e-sec)
+ sb!xc:internal-time-units-per-second)
+ (- msec e-msec))
+ c-msec msec
+ c-sec sec)))
+ now)))

   (defun system-internal-run-time ()
     (multiple-value-bind (ignore utime-sec utime-usec stime-sec stime-usec)
--
1.7.3.4

Stas Boukarev (stassats) on 2012-08-03
Changed in sbcl:
status: New → Confirmed
importance: Undecided → Medium

I'm not sure that's the right approach. It'd be nicer to just use a
proper monotonic clock (e.g. POSIX clock_gettime() with
CLOCK_MONOTONIC).

--
Juho Snellman

Lutz Euler (lutz-euler) wrote :

I like Juho's suggestion from #4.
Does this mean that one needs to call sysconf at SBCL
startup time to find out whether CLOCK_MONOTONIC
is supported and else fall back to the approach from #2?

nixie (onixie) wrote :

CLOCK_MONOTONIC would be nicer on supported platform.

I test against some other CL implementations.
Some give meaningless overflowed unsigned result, some just return negative elapse which breaks CL standard.
So I think reset the elapse to 0 can be a kind of better remedy.

Changed in sbcl:
assignee: nobody → David Lichteblau (david-lichteblau)
Stas Boukarev (stassats) on 2013-09-19
Changed in sbcl:
assignee: David Lichteblau (david-lichteblau) → nobody
Ub User (ubcock) wrote :

This bug also affects the Win32 version of GET-INTERNAL-REAL-TIME in win32.lisp.

James Kalenius (aeshtaer) wrote :

I got a similar error on macOS Sierra 10.12.6 with SBCL 1.3.18.105-f0b6b7c23, unintentionally while building something. scymtym suggested it could have been NTP setting the clock back, which seems plausible.

Backtrace attached. Just posting on the off chance it helps.

To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Duplicates of this bug

Other bug subscribers