'''`[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 "-------------------------" exit ====== Note 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 ..} ::res ====== first [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 = 1 ====== it 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 [http://core.tcl.tk/thread/tktview?name=2980143fff]. <> thread