It seems puts will block or push data in the background. If it is interrupted with alarm it happily continues. Here is a small patch to allow TclX alarm to interrupt blocking output [puts]. Is this a good idea?
Index: generic/tclIO.c =================================================================== --- generic/tclIO.c +++ generic/tclIO.c @@ -2416,16 +2416,17 @@ * write any more output at this time. */ if (written < 0) { /* - * If the last attempt to write was interrupted, simply retry. + * If the last attempt to write was interrupted, Check for async events or simply retry. */ - if (errorCode == EINTR) { - errorCode = 0; - continue; + if (!Tcl_AsyncReady() || Tcl_AsyncInvoke(interp, TCL_OK) == TCL_OK) { + errorCode = 0; + continue; + } } /* * If the channel is non-blocking and we would have blocked, start * a background flushing handler and break out of the loop