Errors remember the original thread

db4
Slava Pestov 2008-02-27 19:23:22 -06:00
parent a5503782d7
commit ed4506c0b0
12 changed files with 133 additions and 119 deletions

View File

@ -367,7 +367,7 @@ TUPLE: callback-context ;
] if ; ] if ;
: do-callback ( quot token -- ) : do-callback ( quot token -- )
init-error-handler init-catchstack
dup 2 setenv dup 2 setenv
slip slip
wait-to-return ; inline wait-to-return ; inline

View File

@ -1,11 +1,11 @@
! Copyright (C) 2004, 2007 Slava Pestov. ! Copyright (C) 2004, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
IN: bootstrap.stage1 IN: bootstrap.stage1
USING: arrays debugger generic hashtables io assocs USING: arrays debugger generic hashtables io assocs
kernel.private kernel math memory namespaces parser kernel.private kernel math memory namespaces parser
prettyprint sequences vectors words system splitting prettyprint sequences vectors words system splitting
init io.files bootstrap.image bootstrap.image.private vocabs init io.files bootstrap.image bootstrap.image.private vocabs
vocabs.loader system ; vocabs.loader system debugger continuations ;
{ "resource:core" } vocab-roots set { "resource:core" } vocab-roots set
@ -40,7 +40,14 @@ vocabs.loader system ;
[ [
"resource:core/bootstrap/stage2.factor" "resource:core/bootstrap/stage2.factor"
dup resource-exists? [ dup resource-exists? [
run-file [ run-file ]
[
:c
dup print-error flush
"listener" vocab
[ restarts. vocab-main execute ]
[ die ] if*
] recover
] [ ] [
"Cannot find " write write "." print "Cannot find " write write "." print
"Please move " write image write " to the same directory as the Factor sources," print "Please move " write image write " to the same directory as the Factor sources," print

View File

@ -51,66 +51,60 @@ SYMBOL: bootstrap-time
! Wrap everything in a catch which starts a listener so ! Wrap everything in a catch which starts a listener so
! you can see what went wrong, instead of dealing with a ! you can see what went wrong, instead of dealing with a
! fep ! fep
[
! We time bootstrap
millis >r
default-image-name "output-image" set-global ! We time bootstrap
millis >r
"math help handbook compiler tools ui ui.tools io" "include" set-global default-image-name "output-image" set-global
"" "exclude" set-global
parse-command-line "math help handbook compiler tools ui ui.tools io" "include" set-global
"" "exclude" set-global
"-no-crossref" cli-args member? [ do-crossref ] unless parse-command-line
! Set dll paths "-no-crossref" cli-args member? [ do-crossref ] unless
wince? [ "windows.ce" require ] when
winnt? [ "windows.nt" require ] when
"deploy-vocab" get [ ! Set dll paths
"stage2: deployment mode" print wince? [ "windows.ce" require ] when
] [ winnt? [ "windows.nt" require ] when
"listener" require
"none" require
] if
[ "deploy-vocab" get [
load-components "stage2: deployment mode" print
run-bootstrap-init
"bootstrap.compiler" vocab [
compile-remaining
] when
] with-compiler-errors
:errors
f error set-global
f error-continuation set-global
"deploy-vocab" get [
"tools.deploy.shaker" run
] [
[
boot
do-init-hooks
[
parse-command-line
run-user-init
"run" get run
stdio get [ stream-flush ] when*
] [ print-error 1 exit ] recover
] set-boot-quot
millis r> - dup bootstrap-time set-global
print-report
"output-image" get resource-path save-image-and-exit
] if
] [ ] [
:c "listener" require
print-error restarts. "none" require
"listener" vocab-main execute ] if
1 exit
] recover [
load-components
run-bootstrap-init
"bootstrap.compiler" vocab [
compile-remaining
] when
] with-compiler-errors
:errors
f error set-global
f error-continuation set-global
"deploy-vocab" get [
"tools.deploy.shaker" run
] [
[
boot
do-init-hooks
[
parse-command-line
run-user-init
"run" get run
stdio get [ stream-flush ] when*
] [ print-error 1 exit ] recover
] set-boot-quot
millis r> - dup bootstrap-time set-global
print-report
"output-image" get resource-path save-image-and-exit
] if

View File

@ -193,6 +193,3 @@ HELP: save-error
{ $values { "error" "an error" } } { $values { "error" "an error" } }
{ $description "Called by the error handler to set the " { $link error } " and " { $link restarts } " global variables after an error was thrown." } { $description "Called by the error handler to set the " { $link error } " and " { $link restarts } " global variables after an error was thrown." }
$low-level-note ; $low-level-note ;
HELP: init-error-handler
{ $description "Called on startup to initialize the catch stack and set a pair of hooks which allow the Factor VM to signal errors to library code." } ;

View File

@ -6,6 +6,7 @@ IN: continuations
SYMBOL: error SYMBOL: error
SYMBOL: error-continuation SYMBOL: error-continuation
SYMBOL: error-thread
SYMBOL: restarts SYMBOL: restarts
<PRIVATE <PRIVATE
@ -24,6 +25,8 @@ SYMBOL: restarts
#! with a declaration. #! with a declaration.
f { object } declare ; f { object } declare ;
: init-catchstack V{ } clone 1 setenv ;
PRIVATE> PRIVATE>
: catchstack ( -- catchstack ) catchstack* clone ; inline : catchstack ( -- catchstack ) catchstack* clone ; inline
@ -169,17 +172,3 @@ M: condition compute-restarts
condition-continuation condition-continuation
[ <restart> ] curry { } assoc>map [ <restart> ] curry { } assoc>map
append ; append ;
<PRIVATE
: init-error-handler ( -- )
V{ } clone set-catchstack
! VM calls on error
[
continuation error-continuation set-global rethrow
] 5 setenv
! VM adds this to kernel errors, so that user-space
! can identify them
"kernel-error" 6 setenv ;
PRIVATE>

View File

@ -1,6 +1,6 @@
USING: alien arrays generic generic.math help.markup help.syntax USING: alien arrays generic generic.math help.markup help.syntax
kernel math memory strings sbufs vectors io io.files classes kernel math memory strings sbufs vectors io io.files classes
help generic.standard continuations system ; help generic.standard continuations system debugger.private ;
IN: debugger IN: debugger
ARTICLE: "errors-assert" "Assertions" ARTICLE: "errors-assert" "Assertions"
@ -80,9 +80,6 @@ HELP: print-error
HELP: restarts. HELP: restarts.
{ $description "Print a list of restarts for the most recently thrown error to the " { $link stdio } " stream." } ; { $description "Print a list of restarts for the most recently thrown error to the " { $link stdio } " stream." } ;
HELP: debug-help
{ $description "Print a synopsis of useful debugger words." } ;
HELP: error-hook HELP: error-hook
{ $var-description "A quotation with stack effect " { $snippet "( error -- )" } " which is used by " { $link try } " to report the error to the user." } { $var-description "A quotation with stack effect " { $snippet "( error -- )" } " which is used by " { $link try } " to report the error to the user." }
{ $examples "The default value prints the error with " { $link print-error } ", followed by a list of restarts and a help message. The graphical listener sets this variable to display a popup instead." } ; { $examples "The default value prints the error with " { $link print-error } ", followed by a list of restarts and a help message. The graphical listener sets this variable to display a popup instead." } ;
@ -169,3 +166,6 @@ HELP: depth
HELP: assert-depth HELP: assert-depth
{ $values { "quot" "a quotation" } } { $values { "quot" "a quotation" } }
{ $description "Runs a quotation. Throws an error if the total number of elements on the stack is not the same before and after the quotation runs." } ; { $description "Runs a quotation. Throws an error if the total number of elements on the stack is not the same before and after the quotation runs." } ;
HELP: init-debugger
{ $description "Called on startup to set a pair of hooks which allow the " { $link throw } " word to function." } ;

View File

@ -5,7 +5,8 @@ math namespaces prettyprint sequences assocs sequences.private
strings io.styles vectors words system splitting math.parser strings io.styles vectors words system splitting math.parser
tuples continuations continuations.private combinators tuples continuations continuations.private combinators
generic.math io.streams.duplex classes compiler.units generic.math io.streams.duplex classes compiler.units
generic.standard vocabs ; generic.standard vocabs threads threads.private init
kernel.private ;
IN: debugger IN: debugger
GENERIC: error. ( error -- ) GENERIC: error. ( error -- )
@ -57,27 +58,30 @@ M: string error. print ;
dup length [ restart. ] 2each dup length [ restart. ] 2each
] if ; ] if ;
: debug-help ( -- )
nl
"Debugger commands:" print
nl
":help - documentation for this error" print
":s - data stack at exception time" print
":r - retain stack at exception time" print
":c - call stack at exception time" print
":edit - jump to source location (parse errors only)" print
":get ( var -- value ) accesses variables at time of the error" print
flush ;
: print-error ( error -- ) : print-error ( error -- )
[ error. flush ] curry [ error. flush ] curry
[ global [ "Error in print-error!" print drop ] bind ] [ global [ "Error in print-error!" print drop ] bind ]
recover ; recover ;
: error-in-thread. ( -- )
error-thread get-global
"Error in thread " write
[
dup thread-id #
" (" % dup thread-name %
", " % dup thread-quot unparse-short % ")" %
] "" make
swap write-object ":" print nl ;
SYMBOL: error-hook SYMBOL: error-hook
[ print-error restarts. debug-help ] error-hook set-global [
error-in-thread.
print-error
restarts.
nl
"Type :help for debugging help." print flush
] error-hook set-global
: try ( quot -- ) : try ( quot -- )
[ error-hook get call ] recover ; [ error-hook get call ] recover ;
@ -260,3 +264,31 @@ M: no-compilation-unit error.
M: no-vocab summary M: no-vocab summary
drop "Vocabulary does not exist" ; drop "Vocabulary does not exist" ;
! Hooks
M: thread error-in-thread ( error thread -- )
initial-thread get-global eq? [
die drop
] [
global [
error-in-thread. print-error flush
] bind
] if ;
<PRIVATE
: init-debugger ( -- )
V{ } clone set-catchstack
! VM calls on error
[
self error-thread set-global
continuation error-continuation set-global
rethrow
] 5 setenv
! VM adds this to kernel errors, so that user-space
! can identify them
"kernel-error" 6 setenv ;
PRIVATE>
[ init-debugger ] "debugger" add-init-hook

View File

@ -0,0 +1,7 @@
IN: temporary
USING: init namespaces sequences math tools.test kernel ;
[ t ] [
init-hooks get [ first "libc" = ] find drop
init-hooks get [ first "io.backend" = ] find drop <
] unit-test

View File

@ -15,7 +15,7 @@ init-hooks global [ drop V{ } clone ] cache drop
dup init-hooks get at [ over call ] unless dup init-hooks get at [ over call ] unless
init-hooks get set-at ; init-hooks get set-at ;
: boot ( -- ) init-namespaces init-error-handler ; : boot ( -- ) init-namespaces init-catchstack ;
: boot-quot ( -- quot ) 20 getenv ; : boot-quot ( -- quot ) 20 getenv ;

View File

@ -46,7 +46,7 @@ M: realloc-error summary drop "Memory reallocation failed" ;
<PRIVATE <PRIVATE
[ H{ } clone mallocs set-global ] "mallocs" add-init-hook [ H{ } clone mallocs set-global ] "libc" add-init-hook
: add-malloc ( alien -- ) : add-malloc ( alien -- )
dup mallocs get-global set-at ; dup mallocs get-global set-at ;

View File

@ -429,7 +429,7 @@ HELP: collect
HELP: each HELP: each
{ $values { "seq" sequence } { "quot" "a quotation with stack effect " { $snippet "( elt -- )" } } } { $values { "seq" sequence } { "quot" "a quotation with stack effect " { $snippet "( elt -- )" } } }
{ $description "Applies the quotation to each element of the sequence in turn." } ; { $description "Applies the quotation to each element of the sequence in order." } ;
HELP: reduce HELP: reduce
{ $values { "seq" sequence } { "identity" object } { "quot" "a quotation with stack effect " { $snippet "( prev elt -- next )" } } { "result" "the final result" } } { $values { "seq" sequence } { "identity" object } { "quot" "a quotation with stack effect " { $snippet "( prev elt -- next )" } } { "result" "the final result" } }
@ -447,7 +447,7 @@ HELP: accumulate
HELP: map HELP: map
{ $values { "seq" sequence } { "quot" "a quotation with stack effect " { $snippet "( old -- new )" } } { "newseq" "a new sequence" } } { $values { "seq" sequence } { "quot" "a quotation with stack effect " { $snippet "( old -- new )" } } { "newseq" "a new sequence" } }
{ $description "Applies the quotation to each element yielding a new element. The new elements are collected into a sequence of the same class as the input sequence." } ; { $description "Applies the quotation to each element of the sequence in order. The new elements are collected into a sequence of the same class as the input sequence." } ;
HELP: change-nth HELP: change-nth
{ $values { "i" "a non-negative integer" } { "seq" "a mutable sequence" } { "quot" "a quotation with stack effect " { $snippet "( elt -- newelt )" } } } { $values { "i" "a non-negative integer" } { "seq" "a mutable sequence" } { "quot" "a quotation with stack effect " { $snippet "( elt -- newelt )" } } }

View File

@ -4,13 +4,12 @@
IN: threads IN: threads
USING: arrays hashtables heaps kernel kernel.private math USING: arrays hashtables heaps kernel kernel.private math
namespaces sequences vectors continuations continuations.private namespaces sequences vectors continuations continuations.private
dlists assocs system combinators debugger prettyprint io init dlists assocs system combinators init boxes ;
boxes ;
SYMBOL: initial-thread SYMBOL: initial-thread
TUPLE: thread TUPLE: thread
name quot error-handler exit-handler name quot exit-handler
id id
continuation state continuation state
mailbox variables sleep-entry ; mailbox variables sleep-entry ;
@ -60,11 +59,10 @@ threads global [ H{ } assoc-like ] change-at
PRIVATE> PRIVATE>
: <thread> ( quot name error-handler -- thread ) : <thread> ( quot name -- thread )
\ thread counter <box> [ ] { \ thread counter <box> [ ] {
set-thread-quot set-thread-quot
set-thread-name set-thread-name
set-thread-error-handler
set-thread-id set-thread-id
set-thread-continuation set-thread-continuation
set-thread-exit-handler set-thread-exit-handler
@ -179,20 +177,8 @@ M: real sleep
] 1 (throw) ] 1 (throw)
] "spawn" suspend 2drop ; ] "spawn" suspend 2drop ;
: default-thread-error-handler ( error thread -- )
global [
"Error in thread " write
dup thread-id pprint
" (" write
dup thread-name pprint ")" print
"spawned to call " write
thread-quot short.
nl
print-error flush
] bind ;
: spawn ( quot name -- thread ) : spawn ( quot name -- thread )
[ default-thread-error-handler ] <thread> [ (spawn) ] keep ; <thread> [ (spawn) ] keep ;
: spawn-server ( quot name -- thread ) : spawn-server ( quot name -- thread )
>r [ [ ] [ ] while ] curry r> spawn ; >r [ [ ] [ ] while ] curry r> spawn ;
@ -202,6 +188,8 @@ M: real sleep
[ >r set-namestack set-datastack r> call ] 3curry [ >r set-namestack set-datastack r> call ] 3curry
"Thread" spawn drop ; "Thread" spawn drop ;
GENERIC: error-in-thread ( error thread -- )
<PRIVATE <PRIVATE
: init-threads ( -- ) : init-threads ( -- )
@ -209,13 +197,13 @@ M: real sleep
<dlist> 42 setenv <dlist> 42 setenv
<min-heap> 43 setenv <min-heap> 43 setenv
initial-thread global initial-thread global
[ drop f "Initial" [ die ] <thread> ] cache [ drop f "Initial" <thread> ] cache
<box> over set-thread-continuation <box> over set-thread-continuation
f over set-thread-state f over set-thread-state
dup register-thread dup register-thread
set-self ; set-self ;
[ self dup thread-error-handler call stop ] [ self error-in-thread stop ]
thread-error-hook set-global thread-error-hook set-global
PRIVATE> PRIVATE>