Debugging Threads

If a thread sustains an untrapped error, its execution is suspended in the normal way. If the Pause on Error option is set, all other threads are paused. If Pause on Error option is not set, other threads will continue running and it is possible for another thread to encounter an error and suspend (see the Dyalog for Microsoft Windows Installation and Configuration Guide).

Using the facilities provided by the Tracer and the Threads Tool (see the Dyalog for Microsoft Windows UI Guide) it is possible to interrupt (suspend) and restart individual threads, and to pause and resume individual threads, so any thread may be in one of three states - running, suspended or paused.

The Tracer and the Session may be connected with any suspended thread and you can switch the attention of the Session and the Tracer between suspended threads using )TID or by clicking on the appropriate tab in the Tracer. At this point, you may:

  • Examine and modify local variables for the currently suspended thread.
  • Trace and edit functions in the current thread.
  • Cut back the stack in the currently suspended thread.
  • Restart execution.
  • Start new threads

The error message from a thread other than the base is prefixed with its thread number:

260:DOMAIN ERROR
Div[2] rsltnum÷div
      ^

State indicator displays: )SI and )SINL have been extended to show threads' tree-like calling structure.

      )SI
·   #.Calc[1]
&5
·   ·   #.DivSub[1]
·   &7
·   ·   #.DivSub[1]
·   &6
·   #.Div[2]*
&4
#.Sub[3]
#.Main[4]

Here, Main has called Sub, which has spawned threads 4 and 5 with functions: Div and Calc. Function Div, after spawning DivSub in each of threads 6 and 7, have been suspended at line [2].

Removing stack frames using Quit from the Tracer or from the session affects only the current thread. When the final stack frame in a thread (other than the base thread) is removed, the thread is expunged.

)RESET removes all but the base thread.

Note the distinction between a suspended thread and a paused thread.

A suspended thread is stopped at the beginning of a line in a defined function or operator. It may be connected to the Session so that expressions executed in the Session do so in the context of that thread. It may be restarted by executing →line (typically, →⎕LC).

A paused thread is an inactive thread that is currently being ignored by the thread scheduler. A paused thread may be paused within a call to ⎕DQ, a call on an external function, at the beginning of a line, or indeed at any of the thread-switching points described earlier in this chapter.

A paused thread may be resumed only by the action of a menu item or button. A paused thread resumes only in the sense that it ceases to be ignored by the thread scheduler and will therefore be switched back to at some point in the future. It does not actually continue executing until the switch occurs.