thread::errorproc establishes a handler for errors that occur in commands that are executed via thread::send -async. This handler is process-global: It is shared by all threads, and it can be set from any thread. errorproc will be invoked in whichever thread set errorproc - not the master thread, nor in the thread that generates the error.
The following script illustrates the interaction of thread::errorproc and bgerror when threads raise errors. Each test occurs during a vwait to ensure the event loop is running.
puts "Tcl: [package require Tcl]"
puts "Thread: [package require Thread]"
namespace eval d {}
proc d::bgerror args {puts "\[BGERROR\]: $args"}
proc d::errorproc args {puts "\[THREAD-ERROR\]: $args"}
interp bgerror {} d::bgerror
thread::errorproc d::errorproc
set t0 [thread::create thread::wait]
puts "-------------------------"
after 100 {incr ::done}
after 10 {throw {TEST AFTER} "Error in after!"}
vwait ::done
puts "-------------------------"
after 100 {incr ::done}
thread::send -async $t0 {throw {TEST INTHREAD ASYNC RESULT} "Error in thread (async with result)!"} ::res
vwait ::done
puts "res is $res"
puts "-------------------------"
after 100 {incr ::done}
thread::send -async $t0 {throw {TEST INTHREAD ASYNC VOID} "Error in thread (async void)!"}
vwait ::done
puts "-------------------------"
after 100 {
try {
thread::send $t0 {throw {TEST INTHREAD SYNCHRONOUS} "Error in thread (synchronous)!"}
} on error {e o} {
puts "\[CAUGHT-ERROR\]: $e"
} finally {
incr ::done
}
}
vwait done
puts "-------------------------"
exitNote the strange result when -async is used with a result variable (the 2nd test):
Tcl: 8.6.4
Thread: 2.7.2
-------------------------
[BGERROR]: {Error in after!} {-errorcode {TEST AFTER} -code 1 -level 0 -errorstack {INNER {returnImm {Error in after!} {-errorcode {TEST AFTER}}}} -errorinfo {Error in after!
while executing
"throw {TEST AFTER} "Error in after!""
("after" script)} -errorline 1}
-------------------------
[THREAD-ERROR]: tid0x7f379951c700 {Error in thread (async with result)!
while executing
"throw {TEST INTHREAD ASYNC RESULT} "Error in thread (async with result)!""}
[BGERROR]: {Error in thread (async with result)!} {-code 1 -level 0 -errorstack {INNER {returnImm {Error in after!} {-errorcode {TEST AFTER}}}} -errorcode NONE -errorinfo {Error in thread (async with result)!} -errorline 1}
res is Error in thread (async with result)!
-------------------------
[THREAD-ERROR]: tid0x7f379951c700 {Error in thread (async void)!
while executing
"throw {TEST INTHREAD ASYNC VOID} "Error in thread (async void)!""}
-------------------------
[CAUGHT-ERROR]: Error in thread (synchronous)!
-------------------------With the test script:
% thread::send -async $t0 {throw ..} ::resfirst thread::errorproc fires, then bgerror. This could be useful, as bgerror sees more information than errorproc ... but the error dictionary is not in great shape:
-code = 1
-level = 0
-errorstack = "INNER {returnImm {Error in after!} {-errorcode {TEST AFTER}}}"
-errorcode = NONE
-errorinfo = "Error in thread (async with result)!"
-errorline = 1it looks like everything but -errorinfo comes from the previous error, and -errorcode is simply wrong. -errorcode NONE might be a good way to filter these errors out if you're using errorproc and bgerror together.
PYK 2015-04-25: It's not that -errorcode is wrong, just that thread only sends the -errorinfo, not the whole return options dictionary to thread::errorproc. When bgerrror is triggered as a result of the failed variable write, a return options dictionary is generated, but isn't going to contain any useful information other than the -errorinfo value, which thread::errorproc also receives.
aspect: this seems to be an effect of [L1 ].