Liking cljdoc? Tell your friends :D
Clojure only.

com.blockether.vis.internal.foundation.pty

Pure-Java pseudo-terminal for shell_bg — NO JNA, NO extracted native helper, NO external tmux. Everything is a java.lang.foreign (Panama FFM) downcall into the platform libc, so it survives GraalVM native-image the same way the rest of vis's FFM surface (fff / rift / ruff / tree-sitter) does.

Why FFM and not pty4j:

  • pty4j drags in JNA and ships its own compiled libpty that it extracts to a temp dir at runtime — two native-image headaches (reflection metadata for JNA + a resource-extraction dance for the .dylib/.so).
  • The obvious pure-FFM shortcut — call libc forkpty then execve in the child — does NOT work from a JVM: invoking an FFM downcall MethodHandle after fork() is not async-signal-safe and SIGBUSes the child. (Verified.)
  • posix_spawn sidesteps that entirely: libc does the fork+exec ATOMICALLY in native code, so vis only ever issues ONE parent-side downcall and never runs any JVM code in the child. Paired with openpty (master/slave fds) + a dup2 of the slave onto the child's 0/1/2, the child gets a real TTY: isatty() is true, $TERM is honoured, stdin is writable.

Public surface — spawn! returns a PLAIN MAP (not a java.lang.Process; a runtime proxy/gen-class would break native-image), shaped for the internal.foundation.shell background pump:

{:pid <long> OS pid (a genuine child — ProcessHandle/of works, unlike a pty4j process) :in <java.io.InputStream> master-fd reader (a real piped stream) :send (fn [^bytes b]) write bytes to the master (the stdin channel) :wait (fn [] <int>) block until exit, reap, return the exit code :alive? (fn [] <bool>) :destroy (fn [force?]) SIGTERM (false) / SIGKILL (true) the child}

Pure-Java pseudo-terminal for `shell_bg` — NO JNA, NO extracted native helper,
NO external `tmux`. Everything is a `java.lang.foreign` (Panama FFM) downcall
into the platform libc, so it survives GraalVM native-image the same way the
rest of vis's FFM surface (fff / rift / ruff / tree-sitter) does.

Why FFM and not pty4j:
- pty4j drags in JNA *and* ships its own compiled `libpty` that it extracts to
  a temp dir at runtime — two native-image headaches (reflection metadata for
  JNA + a resource-extraction dance for the .dylib/.so).
- The obvious pure-FFM shortcut — call libc `forkpty` then `execve` in the
  child — does NOT work from a JVM: invoking an FFM downcall MethodHandle after
  `fork()` is not async-signal-safe and SIGBUSes the child. (Verified.)
- `posix_spawn` sidesteps that entirely: libc does the fork+exec ATOMICALLY in
  native code, so vis only ever issues ONE parent-side downcall and never runs
  any JVM code in the child. Paired with `openpty` (master/slave fds) + a
  `dup2` of the slave onto the child's 0/1/2, the child gets a real TTY:
  `isatty()` is true, `$TERM` is honoured, stdin is writable.

Public surface — `spawn!` returns a PLAIN MAP (not a `java.lang.Process`; a
runtime `proxy`/`gen-class` would break native-image), shaped for the
`internal.foundation.shell` background pump:

  {:pid      <long>              OS pid (a genuine child — `ProcessHandle/of`
                                 works, unlike a pty4j process)
   :in       <java.io.InputStream>   master-fd reader (a real piped stream)
   :send     (fn [^bytes b])     write bytes to the master (the stdin channel)
   :wait     (fn [] <int>)       block until exit, reap, return the exit code
   :alive?   (fn [] <bool>)
   :destroy  (fn [force?])       SIGTERM (false) / SIGKILL (true) the child}
raw docstring

spawn!clj

(spawn! {:keys [command dir env cols rows] :or {cols 120 rows 40}})

Spawn command (a vector of program + args) under a real pseudo-terminal. Options: :dir (working dir string), :env (Map string->string), :cols, :rows. Returns the handle map documented on the namespace.

Spawn `command` (a vector of program + args) under a real pseudo-terminal.
Options: :dir (working dir string), :env (Map string->string), :cols, :rows.
Returns the handle map documented on the namespace.
sourceraw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close