SIGINFO Handler for BSD Systems

This patch adds support for the SIGINFO signal on BSD systems (FreeBSD, OpenBSD, macOS). Pressing Ctrl+T while J is running displays status information about the current execution, following the same convention used by other BSD utilities like dd, cp, and sleep.

Patch: siginfo.patch


What It Does

When you press Ctrl+T during a long-running J computation, jconsole displays a single-line status showing:


Example Output

jconsole: running, 2.5s 1.0G (depth 1)
jconsole: idle, 45.2s 512.0K (depth 0)
jconsole: running myfunc in /tmp/test.ijs:5, 3m02s 2.1G (depth 3)
jconsole: idle, 1.2s 703.5K/1.0G hwm:128.7M (depth 0)
jconsole: [ATTN] running, 10.5s 4.2G (depth 2, 4 threads)

Output Format Breakdown

Component Description Example
State Current execution state running, idle
Verb Currently executing verb name myfunc
Location Script file and line in /tmp/test.ijs:5
Uptime Session duration 2.5s, 3m02s
Memory Current usage 1.0G, 512.0K
Limit Memory limit (if set via 9!:21) /1.0G
HWM High water mark (if >10% above current) hwm:128.7M
Depth Call stack depth (depth 3)
Threads Thread count (if >1) 4 threads
Interrupt Pending interrupt indicator [ATTN], [BREAK]

Why SIGINFO?

On BSD systems, SIGINFO is a standard mechanism for querying process status. Many Unix utilities support it:

This patch brings J in line with BSD conventions, making it easy to check on long-running computations without interrupting them.


Technical Details

Signal Handling

The handler is registered alongside the existing SIGINT handler in jsrc/jconsole.c:

#if defined(SIGINFO)
  signal(SIGINFO, siginfo_handler);
#endif

The #if defined(SIGINFO) guard ensures the code only compiles on systems that support SIGINFO (BSD variants). On Linux and Windows, this code is simply not included.

Async-Signal Safety

Signal handlers must be async-signal-safe, meaning they can only call certain reentrant functions. This handler:

Memory Calculation

Memory usage is read from J’s internal tracking:

I memused = jm->malloctotal + jm->malloctotalremote;
I memhwm = jm->malloctotalhwmk;   // high water mark
I memlimit = jst->mmax;           // allocation limit

The limit is only displayed if explicitly set (via 9!:21) to something smaller than the default maximum.

Accessing Interpreter State

The handler accesses J’s internal structures to gather status information:


Usage Examples

Checking Progress on a Long Computation

   +/ i. 5e9    NB. Sum of first 5 billion integers

While this runs, press Ctrl+T:

jconsole: running, 2.0s 64.0G (depth 1)

With a Memory Limit Set

   9!:21 (1e9)  NB. Set 1GB memory limit
   +/ i. 1e7

Press Ctrl+T after the computation:

jconsole: idle, 0.8s 703.5K/1.0G hwm:128.7M (depth 0)

This shows current usage (703.5K), the limit (1.0G), and the peak usage during the computation (128.7M).

Running a Named Verb

   slowfn =: 3 : '+/ i. y'
   slowfn 1e8

Press Ctrl+T:

jconsole: running slowfn, 1.5s 1.0G (depth 2)

Platform Support

Platform Supported
FreeBSD Yes
OpenBSD Yes
macOS Yes
Linux No (SIGINFO not available)
Windows No (SIGINFO not available)

On unsupported platforms, the patch has no effect — the code is simply not compiled.


Applying the Patch

cd /path/to/jsource
git apply siginfo.patch

Then rebuild jconsole:

cd make2
./build_jconsole.sh

The patch only modifies jsrc/jconsole.c and does not affect libj or other components.