Repository navigation
Conversation
The native reaper already writes the child's exit status into the event pipe, but ghostel--events-filter discarded it before deleting the pipe, so the sentinel only saw "finished" and an rc=0 exit and an rc=1 exit were indistinguishable to exit hooks. Record the status as a process property before the deletion and pass it to ghostel-exit-functions as a third argument. The status is nil when it cannot be determined, and a signal death reports 128 plus the signal number on both the native and Emacs-PTY paths, where process-exit-status alone reports the bare signal number. Handlers that declare two arguments keep the old (BUFFER EVENT) contract; the sender checks func-arity per handler. Closes dakra#744. Session: ef458615-ef53-4c61-a763-6f1d0fdc2e4c
|
@a-min-7 thanks. Would you also be ok with PR #748 ? |
|
Fair enough on the convention — One thing before merging: the newline framing makes the Elisp require the new module. With a pre-#748 module the filter holds the bare number forever and never calls One documentation point: "same strings on both backends" holds for normal exits only. SIGTERM gives Minor, though the newline framing makes it load-bearing: If #748 goes in with those addressed, I'll close #746 — the two-argument hook plus the synthesized strings already covers what prompted it (herdr telling a refused attach from a clean exit without reaching into internals), and the convention argument wins. Environment: |
|
OK, it's merged and I also triggered a new release. |
|
Thanks — that was quick. Merged plus a release is more than I expected today; the two-argument hook is the smaller and more idiomatic change, and I'm happy to have lost that argument. I'll close out my branch here. |
ghostel-exit-functionsruns before the buffer is reaped, which is the right place for a client to react to its own child dying — but on the native-PTY path the child's exit status never reached it. The native reaper writes the status as a bare number into the event pipe;ghostel--events-filterdeletes the pipe without publishing it, so the sentinel surfaces"finished"and an rc=0 exit and an rc=1 exit are indistinguishable. This is the API gap behind herdr.el's takeover prompt, which currently re-reads the event stream through:aroundadvice onghostel--events-filter.This records the status before the deletion and passes it to
ghostel-exit-functionsas a third argument, as agreed in #744.New contract:
(BUFFER EVENT STATUS).STATUSis an integer, or nil when it cannot be determined.process-exit-statusalone reports the bare signal number on the Emacs-PTY path, so the sentinel normalizes it; the native reaper already used 128 plus the signal number.(BUFFER EVENT): the runner checksfunc-arityper handler, so existing hooks (ghostel-eshell--visual-exitincluded) do not change.Measured against a real refusal on herdr 0.9.1, native-PTY path, module built from this branch:
herdr agent attachto a held pane (refused; stderr:terminal … already has an attached client; retry with --takeover)"finished\n""finished\n""finished\n"EVENT is identical in all three; STATUS is the distinguishing value.
This fixes the status half of #744 only; the stderr half remains open. The child's stderr still does not render into the VT — re-measured empty at hook time in the same run. The takeover prompt no longer needs it now that the status is authoritative, but it is a separate gap and is not addressed here.
Version floor for consumers. This adds a third hook argument, so a consumer that gates on the status should require a ghostel release containing this change. herdr.el's fork keeps its
:aroundworkaround onghostel--events-filteruntil such a release exists; itsPackage-Requiresthen needs the corresponding ghostel minimum.Test:
ghostel-test-exec-exit-hook-receives-statusruns rc=0, rc=1 and SIGTERM cases on both local PTY backends, pins the three-argument contract, and asserts that a two-argument handler is still called. It fails against the pre-change code, where the three-argument handler never receives a status.Refs #744.