According to the documentation, `TimeConstrained` generates an interrupt which interrupts the computation. This interrupt is treated just like an abort, at least in the sense that it respects `AbortProtect`.

I want to see the contents of the stack at the time the abort is generated, before the aborted evaluation is removed from the stack. I tried this:

    changeAbort[] :=
     (
      Unprotect[Abort];
      testAbort = True;
      Abort[args___] :=
       (
         Print[Stack[_]]; (* in real life, to a log file *)
         Block[{testAbort = False}, Abort[args]]
       ) /; testAbort
      Protect[Abort];
     )

This works for aborts that I generate myself. For example,

    While[True, Abort[]]

aborts and prints the following stack trace:

    (* 
    {While[True,Abort[]],Print[Stack[_]];Block[{testAbort=False},Abort[]],Print[Stack[_]]}
    *)

Along (spiritually) similar lines, I can print the the stack at the time a message is displayed with this code:

    Internal`AddHandler["Message", Print[Stack[_]]&];

Getting back to `TimeConstrained`, neither of the following give me a stack trace:

    changeAbort[];TimeConstrained[While[True, Null], 1]
    TimeConstrained[changeAbort[]; While[True, Null], 1]

The last line was written in case `TimeConstrained` was implemented by temporarily redefining `Abort`. Unfortunately, it doesn't work.

Is there some way to intercept the interrupt generated by `TimeConstrained` so that I can get a stack trace of the aborted computation, before it is removed from the stack?