Skip to content

Capture writes to standard_error from evaluated code - #3

Merged
bbatsov merged 3 commits into
mainfrom
stderr-capture
Nov 7, 2026
Merged

bbatsov merged 3 commits into
mainfrom
stderr-capture

Conversation

@bbatsov

@bbatsov bbatsov commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

What evaluated code writes to standard_error used to end up on the server's console, so clients never saw it. There's only one standard_error per node, so capturing it means taking over a device the whole node shares. That's why it's opt-in for embedded servers and turned on only in bin/dialtone, bin/repartee and mix repartee.server. Writes from the rest of the node, and from session processes between evals, still go to the console.

chaser shows stderr as streamed output now, rather than as an error block per chunk.

This replaces #2, which got closed when the branch it was based on went away.

Erlang has a single standard_error device per node, so output that
evaluated code wrote there ended up on the server's console instead of
the client. dialtone_stderr takes over the device's name and forwards
writes from eval workers (found through their group leader) to their
session's IO server, which sends them to the client as err. Everything
else goes to the original device, and so do writes from session
processes while no request is running. A forwarded write whose IO server
dies gets an error instead of waiting forever.

Taking over a node-wide device is too much for an embedded server to do
on its own, so it's opt-in through dialtone:capture_stderr/0 or the
capture_stderr app env. The standalone server turns it on.
Like bin/dialtone, bin/repartee and mix repartee.server own their node,
so they can send what evaluated code writes to :standard_error to the
client. That includes Elixir's parse warnings.
chaser treated every err in a response as a failed eval and printed each
chunk as its own error block. Now that dialtone streams stderr as err,
plain err chunks are printed as they arrive (in red), and the error
block is kept for responses with an ex.
@bbatsov
bbatsov merged commit ec4a6c8 into main Nov 7, 2026
10 checks passed
@bbatsov
bbatsov deleted the stderr-capture branch November 7, 2026 09:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant