Skip to content

Conversation

@jpco
Copy link
Collaborator

@jpco jpco commented Dec 1, 2024

This PR adds a few things:

First, an -n flag for wait, which corresponds with waitpid(WNOHANG). This can be used to implement a check-wait function during %prompt, something some shells do automatically.

To support that use case, there is a new hook function %echo-status, which is called when any process is ewait()ed for, and performs the work of printing the "interesting" signal terminations. A default implementation is provided which should be the same as the current behavior. A quick-and-dirty way to hack on this function is to simply set fn-%echo-status = echo to see how every process exits:

; fn-%echo-status = echo
; cat /usr/share/dict/words | head -5 | wc -c
18
32920 exited 0
32919 exited 0
32918 signaled sigpipe

To make a backwards-compatible %echo-status possible, this PR also adds a new $&sigmessage primitive which externalizes the sigmessage() function. This seems generally useful for signal exception handlers as well; the %interactive-loop function has been modified to use this primitive.

; echo $pid 
34157
; echo $signals 
.sigint /sigquit /sigterm sigpoll sigurg
; # here we run some kills in another terminal
; caught unexpected signal: sigpoll: pollable event occurred
; caught unexpected signal: sigurg: urgent condition on i/o channel

Putting these all together, the following enables the "check-wait" behavior on prompt like in other, job controlling shells:

fn check-wait {
  local (
    fn %echo-status pid did status {
      if {~ $did signaled} {
        echo >[1=2] $pid terminated on signal: <={$&sigmessage $status}
      } {
        echo >[1=2] $pid exited with status $status
      }
    }
  ) $&wait -n
}

let (p = $fn-%prompt)
fn %prompt {
  check-wait
  $p
}

@jpco
Copy link
Collaborator Author

jpco commented Dec 2, 2024

Some caveats/potential alternatives:

  • Bikeshedding welcome. %echo-status has been renamed twice already!
  • %echo-status could be called directly from %pipe, %background, %run (with Use the %run hook function for running binaries. #90), wait, etc., instead of being built-in to every single ewait(), including things like backquotes and heredocs. (actually, %here doesn't ewait() when it should -- $&here leaks child processes #150 -- and I discovered that using %echo-status. Maybe that justifies the version as-written...)
  • %echo-status, like other hook functions, must be dynamically bound to do anything. Also, it's not currently noexport. Should it be?
  • The $echo-status-pid variable is awkward, but it allows people to override %echo-status without having to account for the fact that only sometimes we want the pid printed. Is there a less-awkward way to do the same thing?

A number of the questions I have are in the general category of when we would want to have %echo-status called and when we don't. For example, how many lines do we expect the following to print?

; local (fn-%echo-status = echo) cat <{es -c 'cat <<< blah\n'}

@jpco
Copy link
Collaborator Author

jpco commented Dec 3, 2024

Here's something potentially interesting that wait -n and %echo-status help make posisble (along with sigchld and a couple other bits): a wait-any function that "cleanly" waits for only one of several child pids) https://gist.github.com/jpco/b746ecb7207e1b26da67a71d9c4f0d10

It's only a sketch (note the awkward use of %read as a stand-in for "block until exception", and the fact it doesn't check its arguments for validity at all), but I've been pondering some kind of wait-any function for a while and it's neat that this PR seems to make it possible. Notice in particular that it avoids quietly "eating" the exit status of the "meddling" child, and it does all this without having to keep track of reaped children after-the-fact, as the shell had to do internally before #128 (with some bugs besides; see #125).

A more process-group-aware es could also account for stopped children in some intelligent way in wait-any.

jpco added a commit to jpco/es-shell that referenced this pull request Mar 10, 2025
This PR combines:
 - PR wryun#149, "Add a few things to make $&waiting more flexible."
 - PR wryun#90, "Use the %run hook function for running binaries."
 - A heap of new logic in proc.c and prim-sys.c, generally much cleaner
   than in the original newjobcontrol branch
 - Support for '+signame' signal handling to sig_ignore in the shell pgrp
 - A draft share/job-control.es script

Overall things seem pretty solid.  It even builds and runs successfully
right now with `-ansi -D_POSIX_C_SOURCE=200112L -pedantic -DGCDEBUG=1`,
which is a pleasant surprise.

It still needs:
 - A lot of testing
 - Some more refactoring of pgroup handling, especially around exit
   statuses
 - Follow-up on WCONTINUED and WIFCONTINUED alternatives in POSIX.1-2001
   (or whether ifdef'ing is worth it)
 - A way to hook the %interactive-loop to add signal handlers and run
   newpgrp on startup (this is a blocker to running job-control.es from
   .esrc right now)
jpco added a commit to jpco/es-shell that referenced this pull request Mar 10, 2025
This PR combines:
 - PR wryun#149, "Add a few things to make $&waiting more flexible."
 - PR wryun#90, "Use the %run hook function for running binaries."
 - A heap of new logic in proc.c and prim-sys.c, generally much cleaner
   than in the original newjobcontrol branch
 - Support for '+signame' signal handling to sig_ignore in the shell pgrp
 - A draft share/job-control.es script

Overall things seem pretty solid.  It even builds and runs successfully
right now with `-ansi -D_POSIX_C_SOURCE=200112L -pedantic -DGCDEBUG=1`,
which is a pleasant surprise.

It still needs:
 - A lot of testing
 - Some more refactoring of pgroup handling, especially around exit
   statuses
 - Follow-up on WCONTINUED and WIFCONTINUED alternatives in POSIX.1-2001
   (or whether ifdef'ing is worth it)
 - A way to hook the %interactive-loop to add signal handlers and run
   newpgrp on startup (this is a blocker to running job-control.es from
   .esrc right now)
jpco added a commit to jpco/es-shell that referenced this pull request Mar 10, 2025
This PR combines:
 - PR wryun#149, "Add a few things to make $&waiting more flexible."
 - PR wryun#90, "Use the %run hook function for running binaries."
 - A heap of new logic in proc.c and prim-sys.c, generally much cleaner
   than in the original newjobcontrol branch
 - Support for '+signame' signal handling to sig_ignore in the shell pgrp
 - A draft share/job-control.es script

Overall things seem pretty solid.  It even builds and runs successfully
right now with `-ansi -D_POSIX_C_SOURCE=200112L -pedantic -DGCDEBUG=1`,
which is a pleasant surprise.

It still needs:
 - A lot of testing
 - Some more refactoring of pgroup handling, especially around exit
   statuses
 - Follow-up on WCONTINUED and WIFCONTINUED alternatives in POSIX.1-2001
   (or whether ifdef'ing is worth it)
 - A way to hook the %interactive-loop to add signal handlers and run
   newpgrp on startup (this is a blocker to running job-control.es from
   .esrc right now)
@jpco jpco marked this pull request as draft March 19, 2025 16:51
@jpco jpco force-pushed the master branch 3 times, most recently from 64361a8 to a23a7a0 Compare September 19, 2025 00:40
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