'''[thread]: -eventmark and send -async''' describes how these two features can interact to cause a deadlock. ** Description ** [PYK] 2015-04-12: `[thread]::configure $thread -eventmark ...` limits the number of asynchronous calls to the thread. If thread ''A'' and thread ''B'' are configured with an `-eventmark`, and thread ''A'' uses the variant of `[thread]::send -async` that specifies a variable in which to store the result of the call, a deadlock can occcur if ''A'''s `-eventmark` limit is reached in the meantime. Apparently, the response from ''B'' to ''A'' that stores the result in the specified variable is subject to the queue limit of ''A''. Because asynchronous calls become blocking when a thread's queue limit is reached, ''A'' ends up blocked in an `-async` call to ''B'', which in turn is blocked waiting for ''A'''s queue to die down so that it can write its response. I think this is a bug because with `-eventmark`, the intent is normally to throttle incoming work, and not to limit responses to calls to other threads, and it can be a real head-scratcher when such a deadlock occurs in a non-trivial threaded program. In versions of [thread] that behave like this, the rule of the to is to not execute `[thread]::send -async ... varname]` from a thread that has been configured with a non-zero `-eventmark` value. Here's a script that illustrates the issue: ====== #! /bin/env tclsh package require Thread set consumer [thread::create { proc eat value { puts [list [thread::id] receive $value] } thread::wait }] thread::configure $consumer -eventmark 10 set filter [thread::create { proc eat value { variable consumer # This command causes the threads to hang. thread::send -async $consumer [list eat [expr {$value * 2}]] [namespace current]::reply # Replace the previous command with this one, and the deadlock resolves. #thread::send -async $consumer [list eat [expr {$value * 2}]] } thread::wait }] thread::send $filter [list variable consumer $consumer] thread::configure $filter -eventmark 10 for {set i 0} {$i < 50} {incr i} { set thread [thread::create { proc go {} { variable filter set value 1 while 1 { incr value 2 #puts [list sending $value to $filter] thread::send -async $filter [list eat $value] } } thread::wait }] thread::send -async $thread [list variable filter $filter] thread::send -async $thread {after 0 [list after idle go]} } vwait forever ====== <> thread