2021-02-11 13:41:10 +00:00
|
|
|
########################################################################
|
|
|
|
# #
|
|
|
|
# This file is part of the ksh 93u+m package #
|
|
|
|
# Copyright (c) 2021 Contributors to ksh 93u+m #
|
|
|
|
# <https://github.com/ksh93/ksh> #
|
|
|
|
# and is licensed under the #
|
|
|
|
# Eclipse Public License, Version 1.0 #
|
|
|
|
# #
|
|
|
|
# A copy of the License is available at #
|
|
|
|
# http://www.eclipse.org/org/documents/epl-v10.html #
|
|
|
|
# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
|
|
|
|
# #
|
|
|
|
# Martijn Dekker <martijn@inlv.org> #
|
|
|
|
# #
|
|
|
|
########################################################################
|
|
|
|
function err_exit
|
|
|
|
{
|
|
|
|
print -u2 -n "\t"
|
|
|
|
print -u2 -r "${Command}[$1]: ${@:2}"
|
|
|
|
let Errors++
|
|
|
|
}
|
|
|
|
alias err_exit='err_exit $LINENO'
|
2021-02-12 23:52:25 +00:00
|
|
|
alias warning='err\_exit $((Errors--,LINENO)) warning:'
|
2021-02-11 13:41:10 +00:00
|
|
|
|
|
|
|
Command=${0##*/}
|
|
|
|
integer Errors=0
|
|
|
|
|
|
|
|
[[ -d $tmp && -w $tmp && $tmp == "$PWD" ]] || { err\_exit "$LINENO" '$tmp not set; run this from shtests. Aborting.'; exit 1; }
|
|
|
|
|
|
|
|
# All the tests here should run with job control on
|
|
|
|
set -o monitor
|
|
|
|
|
Fix most of job control (-m/-o monitor) in scripts
If I haven't missed anything, this should make the non-interactive
aspects of job control in scripts work as expected, except for the
"<command unknown>" issue in the output of 'bg', 'fg' and 'jobs'
(which is not such a high priority as those commands are really
designed for interactive use).
Plus, I believe I now finally understand what these three are for:
* The job.jobcontrol variable is set to nonzero by job_init() in
jobs.c if, and only if, the shell is interactive *and* managed to
get control of the terminal. Therefore, any changing of terminal
settings (tcsetpgrp(3), tty_set()) should only be done if
job.jobcontrol is nonzero. This commit changes several checks for
sh_isoption(SH_INTERACTIVE) to checks for job.jobcontrol for
better consistency with this.
* The state flag, sh_isstate(SH_MONITOR), determines whether the
bits of job control that are relevant for both scripts and
interactive shells are active, which is mostly making sure that a
background job gets its own process group (setpgid(3)).
* The shell option, sh_isoption(SH_MONITOR), is just that. When the
user turns it on or off, the state flag is synched with it. It
should usually not be directly checked for, as the state may be
temporarily turned off without turning off the option.
Prior discussion:
https://www.mail-archive.com/austin-group-l@opengroup.org/msg06456.html
src/cmd/ksh93/bltins/typeset.c, src/cmd/ksh93/sh/args.c:
- Move synching the SH_MONITOR state flag with the SH_MONITOR
shell option from b_set() (the 'set' builtin) to sh_applyopts()
which is indirectly called from b_set() and is also used when
parsing the shell invocation command line. This ensures -m is
properly enabled in both scenarios.
src/cmd/ksh93/sh/jobs.c:
- job_init(): Do not refuse to initialise job control on
non-interactive shells. Instead, skip everything that should only
be done on interactive shells (i.e., everything to do with the
terminal). This function is now even more of a mess than it was
before, so refactoring may be desirabe at some point.
- job_close(), job_set(), job_reset(), job_wait(): Do not reset the
terminal process group (tcsetpgrp()) if job.jobcontrol isn't on.
src/cmd/ksh93/sh/xec.c:
- sh_exec(): TFORK: For SIGINT handling, check the SH_MONITOR
state flag, not the shell option.
- sh_exec(): TFORK: Do not turn off the SH_MONITOR state flag in
forked children. The non-interactive part of job control should
stay active. Instead, turn off the SH_INTERACTIVE state flag so
we don't get interactive shell behaviour (i.e. job control noise
on the terminal) in forked subshells.
- _sh_fork(), sh_ntfork(): Do not reset the terminal process group
(tcsetpgrp()) if job.jobcontrol isn't on. Do not turn off the
SH_MONITOR state flag in forked children.
src/cmd/ksh93/sh/subshell.c: sh_subfork():
- Do not turn off the monitor option and state in forked subshells.
The non-interactive part of job control should stay active.
src/cmd/ksh93/bltins/misc.c: b_bg():
- Check isstate(SH_MONITOR) instead of sh_isoption(SH_MONITOR) &&
job.jobcontrol before throwing a 'no job control' error.
This fixes a minor bug: fg, bg and disown could quietly fail.
src/cmd/ksh93/tests/jobs.sh:
- Add tests for 'fg' with job control IDs (%%, %1) in scripts.
- Add test checking that a background job launched from a subsell
with job control enabled correctly becomes the leader of its own
process group.
Makes progress on: https://github.com/ksh93/ksh/issues/119
2021-02-11 22:05:00 +00:00
|
|
|
# ======
|
|
|
|
# Check job control job IDs: %%, %n. Before 2021-02-11 this did not work for 'fg' in scripts.
|
|
|
|
sleep 1 &
|
|
|
|
kill %% >out 2>&1
|
|
|
|
kill $! 2>/dev/null && err_exit "'kill %%' not working in script (got $(printf %q "$(<out)"))"
|
|
|
|
sleep 1 &
|
|
|
|
kill %2 >out 2>&1
|
|
|
|
kill $! 2>/dev/null && err_exit "'kill %2' not working in script (got $(printf %q "$(<out)"))"
|
|
|
|
sleep .05 &
|
|
|
|
wait >out 2>&1
|
|
|
|
kill $! 2>/dev/null && err_exit "'wait' not working in script (got $(printf %q "$(<out)"))"
|
|
|
|
sleep .05 &
|
|
|
|
wait %% >out 2>&1
|
|
|
|
kill $! 2>/dev/null && err_exit "'wait %%' not working in script (got $(printf %q "$(<out)"))"
|
|
|
|
sleep .05 &
|
|
|
|
wait %1 >out 2>&1
|
|
|
|
kill $! 2>/dev/null && err_exit "'wait %1' not working in script (got $(printf %q "$(<out)"))"
|
|
|
|
sleep .05 &
|
|
|
|
fg >out 2>&1
|
|
|
|
kill $! 2>/dev/null && err_exit "'fg' not working in script (got $(printf %q "$(<out)"))"
|
|
|
|
sleep .05 &
|
|
|
|
fg %% >out 2>&1
|
|
|
|
kill $! 2>/dev/null && err_exit "'fg %%' not working in script (got $(printf %q "$(<out)"))"
|
|
|
|
sleep .05 &
|
|
|
|
fg %1 >out 2>&1
|
|
|
|
kill $! 2>/dev/null && err_exit "'fg %1' not working in script (got $(printf %q "$(<out)"))"
|
|
|
|
sleep 1 &
|
|
|
|
sleep 1 &
|
|
|
|
bg >out 2>&1 || err_exit "'bg' not working in script (got $(printf %q "$(<out)"))"
|
|
|
|
bg %% >out 2>&1 || err_exit "'bg %%' not working in script (got $(printf %q "$(<out)"))"
|
|
|
|
bg %+ >out 2>&1 || err_exit "'bg %+' not working in script (got $(printf %q "$(<out)"))"
|
|
|
|
bg %- >out 2>&1 || err_exit "'bg %-' not working in script (got $(printf %q "$(<out)"))"
|
|
|
|
bg %1 >out 2>&1 || err_exit "'bg %1' not working in script (got $(printf %q "$(<out)"))"
|
|
|
|
bg %2 >out 2>&1 || err_exit "'bg %2' not working in script (got $(printf %q "$(<out)"))"
|
|
|
|
disown >out 2>&1 || err_exit "'disown' not working in script (got $(printf %q "$(<out)"))"
|
|
|
|
disown %% >out 2>&1 || err_exit "'disown %%' not working in script (got $(printf %q "$(<out)"))"
|
|
|
|
disown %+ >out 2>&1 || err_exit "'disown %+' not working in script (got $(printf %q "$(<out)"))"
|
|
|
|
disown %- >out 2>&1 || err_exit "'disown %-' not working in script (got $(printf %q "$(<out)"))"
|
|
|
|
disown %1 >out 2>&1 || err_exit "'disown %1' not working in script (got $(printf %q "$(<out)"))"
|
|
|
|
disown %2 >out 2>&1 || err_exit "'disown %2' not working in script (got $(printf %q "$(<out)"))"
|
|
|
|
kill %- >out 2>&1 || err_exit "'kill %-' not working in script (got $(printf %q "$(<out)"))"
|
|
|
|
kill %+ >out 2>&1 || err_exit "'kill %+' not working in script (got $(printf %q "$(<out)"))"
|
|
|
|
|
|
|
|
# fail gracefully: suppress "Terminated" noise on pre-93u+m ksh93
|
|
|
|
{ wait; } 2>/dev/null
|
|
|
|
|
|
|
|
# =====
|
|
|
|
# Before 2021-02-11, job control was deactivated in subshells
|
|
|
|
# https://www.mail-archive.com/austin-group-l@opengroup.org/msg06456.html
|
2021-02-15 15:41:31 +00:00
|
|
|
(sleep 1 & UNIX95=1 command -p ps -o pid= -o pgid= -p $! 2>/dev/null) | IFS=$' \t' read -r pid pgid
|
Fix most of job control (-m/-o monitor) in scripts
If I haven't missed anything, this should make the non-interactive
aspects of job control in scripts work as expected, except for the
"<command unknown>" issue in the output of 'bg', 'fg' and 'jobs'
(which is not such a high priority as those commands are really
designed for interactive use).
Plus, I believe I now finally understand what these three are for:
* The job.jobcontrol variable is set to nonzero by job_init() in
jobs.c if, and only if, the shell is interactive *and* managed to
get control of the terminal. Therefore, any changing of terminal
settings (tcsetpgrp(3), tty_set()) should only be done if
job.jobcontrol is nonzero. This commit changes several checks for
sh_isoption(SH_INTERACTIVE) to checks for job.jobcontrol for
better consistency with this.
* The state flag, sh_isstate(SH_MONITOR), determines whether the
bits of job control that are relevant for both scripts and
interactive shells are active, which is mostly making sure that a
background job gets its own process group (setpgid(3)).
* The shell option, sh_isoption(SH_MONITOR), is just that. When the
user turns it on or off, the state flag is synched with it. It
should usually not be directly checked for, as the state may be
temporarily turned off without turning off the option.
Prior discussion:
https://www.mail-archive.com/austin-group-l@opengroup.org/msg06456.html
src/cmd/ksh93/bltins/typeset.c, src/cmd/ksh93/sh/args.c:
- Move synching the SH_MONITOR state flag with the SH_MONITOR
shell option from b_set() (the 'set' builtin) to sh_applyopts()
which is indirectly called from b_set() and is also used when
parsing the shell invocation command line. This ensures -m is
properly enabled in both scenarios.
src/cmd/ksh93/sh/jobs.c:
- job_init(): Do not refuse to initialise job control on
non-interactive shells. Instead, skip everything that should only
be done on interactive shells (i.e., everything to do with the
terminal). This function is now even more of a mess than it was
before, so refactoring may be desirabe at some point.
- job_close(), job_set(), job_reset(), job_wait(): Do not reset the
terminal process group (tcsetpgrp()) if job.jobcontrol isn't on.
src/cmd/ksh93/sh/xec.c:
- sh_exec(): TFORK: For SIGINT handling, check the SH_MONITOR
state flag, not the shell option.
- sh_exec(): TFORK: Do not turn off the SH_MONITOR state flag in
forked children. The non-interactive part of job control should
stay active. Instead, turn off the SH_INTERACTIVE state flag so
we don't get interactive shell behaviour (i.e. job control noise
on the terminal) in forked subshells.
- _sh_fork(), sh_ntfork(): Do not reset the terminal process group
(tcsetpgrp()) if job.jobcontrol isn't on. Do not turn off the
SH_MONITOR state flag in forked children.
src/cmd/ksh93/sh/subshell.c: sh_subfork():
- Do not turn off the monitor option and state in forked subshells.
The non-interactive part of job control should stay active.
src/cmd/ksh93/bltins/misc.c: b_bg():
- Check isstate(SH_MONITOR) instead of sh_isoption(SH_MONITOR) &&
job.jobcontrol before throwing a 'no job control' error.
This fixes a minor bug: fg, bg and disown could quietly fail.
src/cmd/ksh93/tests/jobs.sh:
- Add tests for 'fg' with job control IDs (%%, %1) in scripts.
- Add test checking that a background job launched from a subsell
with job control enabled correctly becomes the leader of its own
process group.
Makes progress on: https://github.com/ksh93/ksh/issues/119
2021-02-11 22:05:00 +00:00
|
|
|
if let "pid>0 && pgid>0" 2>/dev/null
|
|
|
|
then kill $pid
|
|
|
|
let "pgid == pid" || err_exit "background job run in subshell didn't get its own process group ($pgid != $pid)"
|
|
|
|
else warning "skipping subshell job control test due to non-compliant 'ps'"
|
|
|
|
fi
|
|
|
|
|
2021-02-11 13:41:10 +00:00
|
|
|
# ======
|
|
|
|
# Before 2021-02-11, using a shared-state ${ command substitution; } twice caused ksh to lose track of all running jobs
|
Fix most of job control (-m/-o monitor) in scripts
If I haven't missed anything, this should make the non-interactive
aspects of job control in scripts work as expected, except for the
"<command unknown>" issue in the output of 'bg', 'fg' and 'jobs'
(which is not such a high priority as those commands are really
designed for interactive use).
Plus, I believe I now finally understand what these three are for:
* The job.jobcontrol variable is set to nonzero by job_init() in
jobs.c if, and only if, the shell is interactive *and* managed to
get control of the terminal. Therefore, any changing of terminal
settings (tcsetpgrp(3), tty_set()) should only be done if
job.jobcontrol is nonzero. This commit changes several checks for
sh_isoption(SH_INTERACTIVE) to checks for job.jobcontrol for
better consistency with this.
* The state flag, sh_isstate(SH_MONITOR), determines whether the
bits of job control that are relevant for both scripts and
interactive shells are active, which is mostly making sure that a
background job gets its own process group (setpgid(3)).
* The shell option, sh_isoption(SH_MONITOR), is just that. When the
user turns it on or off, the state flag is synched with it. It
should usually not be directly checked for, as the state may be
temporarily turned off without turning off the option.
Prior discussion:
https://www.mail-archive.com/austin-group-l@opengroup.org/msg06456.html
src/cmd/ksh93/bltins/typeset.c, src/cmd/ksh93/sh/args.c:
- Move synching the SH_MONITOR state flag with the SH_MONITOR
shell option from b_set() (the 'set' builtin) to sh_applyopts()
which is indirectly called from b_set() and is also used when
parsing the shell invocation command line. This ensures -m is
properly enabled in both scenarios.
src/cmd/ksh93/sh/jobs.c:
- job_init(): Do not refuse to initialise job control on
non-interactive shells. Instead, skip everything that should only
be done on interactive shells (i.e., everything to do with the
terminal). This function is now even more of a mess than it was
before, so refactoring may be desirabe at some point.
- job_close(), job_set(), job_reset(), job_wait(): Do not reset the
terminal process group (tcsetpgrp()) if job.jobcontrol isn't on.
src/cmd/ksh93/sh/xec.c:
- sh_exec(): TFORK: For SIGINT handling, check the SH_MONITOR
state flag, not the shell option.
- sh_exec(): TFORK: Do not turn off the SH_MONITOR state flag in
forked children. The non-interactive part of job control should
stay active. Instead, turn off the SH_INTERACTIVE state flag so
we don't get interactive shell behaviour (i.e. job control noise
on the terminal) in forked subshells.
- _sh_fork(), sh_ntfork(): Do not reset the terminal process group
(tcsetpgrp()) if job.jobcontrol isn't on. Do not turn off the
SH_MONITOR state flag in forked children.
src/cmd/ksh93/sh/subshell.c: sh_subfork():
- Do not turn off the monitor option and state in forked subshells.
The non-interactive part of job control should stay active.
src/cmd/ksh93/bltins/misc.c: b_bg():
- Check isstate(SH_MONITOR) instead of sh_isoption(SH_MONITOR) &&
job.jobcontrol before throwing a 'no job control' error.
This fixes a minor bug: fg, bg and disown could quietly fail.
src/cmd/ksh93/tests/jobs.sh:
- Add tests for 'fg' with job control IDs (%%, %1) in scripts.
- Add test checking that a background job launched from a subsell
with job control enabled correctly becomes the leader of its own
process group.
Makes progress on: https://github.com/ksh93/ksh/issues/119
2021-02-11 22:05:00 +00:00
|
|
|
jobs >/dev/null # get 'Done' messages out of the way
|
|
|
|
sleep 1 & sleep 1 &
|
2021-02-11 13:41:10 +00:00
|
|
|
j1=${ jobs; }
|
|
|
|
[[ $j1 == $'[2] + Running '*$'\n[1] - Running '* ]] || err_exit "sleep jobs not registered (got $(printf %q "$j1"))"
|
|
|
|
: ${ :; } ${ :; }
|
|
|
|
j2=${ jobs; }
|
Fix most of job control (-m/-o monitor) in scripts
If I haven't missed anything, this should make the non-interactive
aspects of job control in scripts work as expected, except for the
"<command unknown>" issue in the output of 'bg', 'fg' and 'jobs'
(which is not such a high priority as those commands are really
designed for interactive use).
Plus, I believe I now finally understand what these three are for:
* The job.jobcontrol variable is set to nonzero by job_init() in
jobs.c if, and only if, the shell is interactive *and* managed to
get control of the terminal. Therefore, any changing of terminal
settings (tcsetpgrp(3), tty_set()) should only be done if
job.jobcontrol is nonzero. This commit changes several checks for
sh_isoption(SH_INTERACTIVE) to checks for job.jobcontrol for
better consistency with this.
* The state flag, sh_isstate(SH_MONITOR), determines whether the
bits of job control that are relevant for both scripts and
interactive shells are active, which is mostly making sure that a
background job gets its own process group (setpgid(3)).
* The shell option, sh_isoption(SH_MONITOR), is just that. When the
user turns it on or off, the state flag is synched with it. It
should usually not be directly checked for, as the state may be
temporarily turned off without turning off the option.
Prior discussion:
https://www.mail-archive.com/austin-group-l@opengroup.org/msg06456.html
src/cmd/ksh93/bltins/typeset.c, src/cmd/ksh93/sh/args.c:
- Move synching the SH_MONITOR state flag with the SH_MONITOR
shell option from b_set() (the 'set' builtin) to sh_applyopts()
which is indirectly called from b_set() and is also used when
parsing the shell invocation command line. This ensures -m is
properly enabled in both scenarios.
src/cmd/ksh93/sh/jobs.c:
- job_init(): Do not refuse to initialise job control on
non-interactive shells. Instead, skip everything that should only
be done on interactive shells (i.e., everything to do with the
terminal). This function is now even more of a mess than it was
before, so refactoring may be desirabe at some point.
- job_close(), job_set(), job_reset(), job_wait(): Do not reset the
terminal process group (tcsetpgrp()) if job.jobcontrol isn't on.
src/cmd/ksh93/sh/xec.c:
- sh_exec(): TFORK: For SIGINT handling, check the SH_MONITOR
state flag, not the shell option.
- sh_exec(): TFORK: Do not turn off the SH_MONITOR state flag in
forked children. The non-interactive part of job control should
stay active. Instead, turn off the SH_INTERACTIVE state flag so
we don't get interactive shell behaviour (i.e. job control noise
on the terminal) in forked subshells.
- _sh_fork(), sh_ntfork(): Do not reset the terminal process group
(tcsetpgrp()) if job.jobcontrol isn't on. Do not turn off the
SH_MONITOR state flag in forked children.
src/cmd/ksh93/sh/subshell.c: sh_subfork():
- Do not turn off the monitor option and state in forked subshells.
The non-interactive part of job control should stay active.
src/cmd/ksh93/bltins/misc.c: b_bg():
- Check isstate(SH_MONITOR) instead of sh_isoption(SH_MONITOR) &&
job.jobcontrol before throwing a 'no job control' error.
This fixes a minor bug: fg, bg and disown could quietly fail.
src/cmd/ksh93/tests/jobs.sh:
- Add tests for 'fg' with job control IDs (%%, %1) in scripts.
- Add test checking that a background job launched from a subsell
with job control enabled correctly becomes the leader of its own
process group.
Makes progress on: https://github.com/ksh93/ksh/issues/119
2021-02-11 22:05:00 +00:00
|
|
|
kill %- %+
|
2021-02-11 13:41:10 +00:00
|
|
|
[[ $j2 == "$j1" ]] || err_exit "jobs lost after shared-state command substitution ($(printf %q "$j2") != $(printf %q "$j1"))"
|
|
|
|
|
|
|
|
# ======
|
|
|
|
exit $((Errors<125?Errors:125))
|