Page MenuHomeFreeBSD

bin/sh: set $! to last foreground job pid on trap
AbandonedPublic

Authored by corvink on Dec 7 2022, 11:20 AM.
Tags
None
Referenced Files
Unknown Object (File)
Fri, Apr 26, 2:09 AM
Unknown Object (File)
Fri, Apr 26, 2:09 AM
Unknown Object (File)
Thu, Apr 25, 8:05 PM
Unknown Object (File)
Dec 20 2023, 7:37 AM
Unknown Object (File)
Oct 12 2023, 12:59 AM
Unknown Object (File)
Sep 30 2023, 7:15 PM
Unknown Object (File)
Apr 5 2023, 10:50 AM
Subscribers

Details

Reviewers
jilles
des
emaste
Summary

When trapsasync is set, a foreground job can be interrupted and a trap
will be executed. This can be used to kill the foreground job and
cleanup the script. At the moment, it's not possible to kill the
foreground job reliable because the pid of the foreground job is not
accessible. This patch allows a trap to get the pid by reading the $!
variable.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped
Build Status
Buildable 48637
Build 45523: arc lint + arc unit

Event Timeline

How do other shells with a similar option handle this? For example, zsh has a TRAPS_ASYNC option, but does not document how to access the interrupted job in the trap action.

When modifying a standard parameter like $!, take care to do this only if a non-standard option (such as set -T) is in use. Otherwise, a standards-compliant script might see an unexpected change. This seems to be the case.

It may be a better alternative to set the interrupted job as the current job (see the if (jp->state == JOBSTOPPED) below), making it accessible using commands like kill %+ or jobs -p %+. The latter can be used (by itself) in a command substitution. Another alternative may be to set a new variable.

bin/sh/jobs.c
1096

Only setting backgndpid and not adjusting bgjob will cause evaluating $! to return one job's process ID but cause another job to be remembered.

1096

$! is normally set to the last process's ID, not the first. This indeed does not match the job's process group ID for pipelines with two or more processes.

It may be a better alternative to set the interrupted job as the current job (see the if (jp->state == JOBSTOPPED) below), making it accessible using commands like kill %+ or jobs -p %+. The latter can be used (by itself) in a command substitution. Another alternative may be to set a new variable.

Thanks for the hint. kill %+ and jobs -p %+ are already working. So, no patch required. Might be a good idea to mention it in the man page.

Thanks for the hint. kill %+ and jobs -p %+ are already working. So, no patch required. Might be a good idea to mention it in the man page.

Feel free to submit a patch for that.

By the way, this will not work if there is a stopped (^Z'ed) job, because %+ (and also %-) will refer to a stopped job when possible.