From: Steffen Nurpmeso <steffen@sdaoden.eu>
To: DASH shell mailing list <dash@vger.kernel.org>,
Denys Vlasenko <vda.linux@googlemail.com>,
Jilles Tjoelker <jilles@stack.nl>
Subject: dash 0.5.11.2, busybox sh 1.32.0, FreeBSD 12.2 sh: spring TTOU but should not i think
Date: Sat, 19 Dec 2020 18:28:38 +0100 [thread overview]
Message-ID: <20201219172838.1B-WB%steffen@sdaoden.eu> (raw)
[-- Attachment #1: Type: text/plain, Size: 1149 bytes --]
Hello.
Long story short, after falsely accusing BSD make of not working
when child shells use monitor mode someone pointed me into the
correct direction, and whereas the major problem was on the mksh
side (that sneaked in via $SHELL even though .. but regardless)
and was already reported, i can report a minor issue with the
mentioned shells nonetheless: with the reproducer (please do not
complain, it tooks hours to get it that short), when run under
supervision of a(ny tested) make(1), they spring a TTOU trap even
though they should not .. i think.
Please run via "make -f jobo.mk SHELL=YOUR-SHELL", and you should
see something like
./mx-test.sh
Starting job reaper (timeout of 2 seconds)
.. waiting for job reaper to come up
TTOU
....
where this TTOU should not happen i would say. It does not happen
with bash nor mksh nor OpenBSD sh and ksh, nor NetBSD sh and eh,
ksh, hmm.
I hope this helps, a nice weekend from Germany i wish,
--steffen
|
|Der Kragenbaer, The moon bear,
|der holt sich munter he cheerfully and one by one
|einen nach dem anderen runter wa.ks himself off
|(By Robert Gernhardt)
[-- Attachment #2: mx-test.sh --]
[-- Type: application/x-sh, Size: 10098 bytes --]
#!/bin/sh -
OBJDIR='/tmp/jobo';export OBJDIR # MANAGED!!
: ${SHELL:=/bin/sh};export SHELL
: ${JOBNO:=1}
: ${JOBWAIT:=2}
: ${JOBMON:=y}
export \
OBJDIR SHELL JOBNO JOBWAIT JOBMON
LC_ALL=C LANG=C TZ=UTC
export LC_ALL LANG TZ
if [ -z "${MAILX__CC_TEST_RUNNING}" ]; then
CHECK=1 RUN_TEST= MAILX=
export CHECK RUN_TEST MAILX
fi
awk='/usr/bin/awk';export awk
cat='/bin/cat';export cat
grep='/usr/bin/grep';export grep
mkdir='/bin/mkdir';export mkdir
rm='/bin/rm';export rm
if [ -z "${MAILX__CC_TEST_RUNNING}" ]; then
MAILX__CC_TEST_RUNNING=y
export MAILX__CC_TEST_RUNNING
rm -rf $OBJDIR
mkdir -p $OBJDIR
exec "${SHELL}" "${0}" "${@}"
fi
cd $OBJDIR || exit 100
DEVELDIFF= DUMPERR=
TESTS_PERFORMED=0 TESTS_OK=0 TESTS_FAILED=0 TESTS_SKIPPED=0
JOBS=0 JOBLIST= JOBDESC= JOBREAPER= JOBSYNC=
SUBSECOND_SLEEP=
( sleep .1 ) >/dev/null 2>&1 && SUBSECOND_SLEEP=y
TESTS_NET_TEST=
[ "${OPT_NET_TEST}" = 1 ] && [ -x ./net-test ] && TESTS_NET_TEST=1
export TESTS_NET_TEST
COLOR_ERR_ON= COLOR_ERR_OFF= COLOR_DBGERR_ON= COLOR_DBGERR_OFF=
COLOR_WARN_ON= COLOR_WARN_OFF=
COLOR_OK_ON= COLOR_OK_OFF=
ESTAT=0
TEST_NAME=
trap "
jobreaper_stop
" EXIT
trap "exit 1" HUP INT QUIT TERM
trap 'echo TTIN' TTIN
trap 'echo TTOU' TTOU
trap 'echo TSTP' TSTP
trap : CHLD
jobreaper_start() {
printf 'Starting job reaper (timeout of %s seconds)\n' ${JOBWAIT}
i=
trap 'i=1' USR1 # "reaper (actually a notify timer only) is up"
(
parent=${$}
sleeper= int=0 hot=0
trap '' EXIT HUP QUIT CHLD
trap 'exit 0' INT
trap '
[ -n "${sleeper}" ] && kill -TERM ${sleeper} >/dev/null 2>&1
int=1 hot=1
' USR1
trap '
[ -n "${sleeper}" ] && kill -TERM ${sleeper} >/dev/null 2>&1
int=1 hot=0
' USR2
trap '
[ -n "${sleeper}" ] && kill -TERM ${sleeper} >/dev/null 2>&1
echo "Stopping job reaper"
exit 0
' TERM
# traps are setup, notify parent that we are up and running
kill -USR1 ${parent} >/dev/null 2>&1
while :; do
int=0
sleep ${JOBWAIT} &
sleeper=${!}
wait ${!}
sleeper=
[ "${int}${hot}" = 01 ] && kill -USR1 ${parent} >/dev/null 2>&1
done
) </dev/null & #>/dev/null 2>&1 &
JOBREAPER=${!}
j=
if [ ${?} -eq 0 ]; then
while :; do
if [ -n "${i}" ]; then
trap '' USR1
return
fi
printf '..%s waiting for job reaper to come up\n' "${j}"
j=' still'
sleep 1 &
wait ${!}
done
fi
JOBREAPER=
printf '%s!! Cannot start the wild job reaper!%s\n' \
"${COLOR_ERR_ON}" "${COLOR_ERR_OFF}"
}
jobreaper_stop() {
[ -n "${JOBREAPER}" ] && kill -TERM ${JOBREAPER} >/dev/null 2>&1
JOBREAPER=
if [ ${JOBS} -gt 0 ]; then
echo 'Cleaning up running jobs'
jtimeout
wait ${JOBLIST}
JOBLIST=
fi
}
jspawn() {
if [ ${JOBNO} -gt 1 ]; then
# We are spawning multiple jobs..
[ ${JOBS} -eq 0 ] && printf '...'
JOBS=`add ${JOBS} 1`
printf ' [%s=%s]' ${JOBS} "${1}"
else
JOBS=1
# Assume problems exist, do not let user keep hanging on terminal
if [ -n "${RUN_TEST}" ]; then
printf '... [%s]\n' "${1}"
fi
fi
[ -n "${JOBMON}" ] && set -m >/dev/null 2>&1
( # Place the job in its own directory to ease file management
trap '' EXIT HUP INT QUIT TERM USR1 USR2
${mkdir} t.${JOBS}.d && cd t.${JOBS}.d &&
eval t_${1} ${JOBS} ${1} &&
${rm} -f ../t.${JOBS}.id
) > t.${JOBS}.io </dev/null & # 2>&1 </dev/null &
i=${!}
[ -n "${JOBMON}" ] && set +m >/dev/null 2>&1
JOBLIST="${JOBLIST} ${i}"
printf '%s\n%s\n' ${i} ${1} > t.${JOBS}.id
# ..until we should sync or reach the maximum concurrent number
[ ${JOBS} -lt ${JOBNO} ] && return
jsync 1
}
jsync() {
if [ ${JOBS} -eq 0 ]; then
[ -n "${TEST_ANY}" ] && printf '\n'
TEST_ANY=
return
fi
[ -z "${JOBSYNC}" ] && [ ${#} -eq 0 ] && return
[ ${JOBNO} -ne 1 ] && printf ' .. waiting\n'
if [ -n "${JOBREAPER}" ]; then
timeout= alldone=
trap 'echo TIMEOUT IN PARENT;timeout=1' USR1
kill -USR1 ${JOBREAPER} >/dev/null 2>&1
loops=0
while [ -z "${timeout}" ]; do
alldone=1
i=0
while [ ${i} -lt ${JOBS} ]; do
i=`add ${i} 1`
[ -f t.${i}.id ] || continue
alldone=
break
done
[ -n "${alldone}" ] && break
if [ -z "${SUBSECOND_SLEEP}" ]; then
loops=`add ${loops} 1`
[ ${loops} -lt 111 ] && continue
sleep 1 &
else
sleep .5 &
fi
echo >&2 PREWAIT
wait ${!}
done
kill -USR2 ${JOBREAPER} >/dev/null 2>&1
trap '' USR1
[ -n "${timeout}" ] && jtimeout
fi
# Now collect the zombies
wait ${JOBLIST}
JOBLIST=
# Update global counters
i=0
while [ ${i} -lt ${JOBS} ]; do
i=`add ${i} 1`
if [ -f t.${i}.id ]; then
{ read pid; read desc; } < t.${i}.id
desc=${desc#${desc%%[! ]*}}
desc=${desc%${desc##*[! ]}}
[ -s t.${i}.io ] && printf >&2 '\n'
printf >&2 '%s!! Timeout: reaped job %s [%s]%s\n' \
"${COLOR_ERR_ON}" ${i} "${desc}" "${COLOR_ERR_OFF}"
TESTS_FAILED=`add ${TESTS_FAILED} 1`
elif [ -s t.${i}.result ]; then
read es tp to tf ts < t.${i}.result
TESTS_PERFORMED=`add ${TESTS_PERFORMED} ${tp}`
TESTS_OK=`add ${TESTS_OK} ${to}`
TESTS_FAILED=`add ${TESTS_FAILED} ${tf}`
TESTS_SKIPPED=`add ${TESTS_SKIPPED} ${ts}`
[ "${es}" != 0 ] && ESTAT=${es}
else
TESTS_FAILED=`add ${TESTS_FAILED} 1`
ESTAT=1
fi
done
JOBS=0
}
jtimeout() {
i=0
while [ ${i} -lt ${JOBS} ]; do
i=`add ${i} 1`
if [ -f t.${i}.id ] &&
read pid < t.${i}.id >/dev/null 2>&1 &&
kill -0 ${pid} >/dev/null 2>&1; then
j=${pid}
[ -n "${JOBMON}" ] && j=-${j}
kill -KILL ${j} >/dev/null 2>&1
else
${rm} -f t.${i}.id
fi
done
}
t_prolog() {
shift
ESTAT=0 TESTS_PERFORMED=0 TESTS_OK=0 TESTS_FAILED=0 TESTS_SKIPPED=0 \
TEST_NAME=${1} TEST_ANY=
printf '%s[%s]%s\n' "" "${TEST_NAME}" ""
}
t_epilog() {
[ -n "${TEST_ANY}" ] && printf '\n'
printf '%s %s %s %s %s\n' \
${ESTAT} \
${TESTS_PERFORMED} ${TESTS_OK} ${TESTS_FAILED} ${TESTS_SKIPPED} \
> ../t.${1}.result
}
t_echo() {
[ -n "${TEST_ANY}" ] && __i__=' ' || __i__=
printf "${__i__}"'%s' "${*}"
TEST_ANY=1
}
t_echook() {
[ -n "${TEST_ANY}" ] && __i__=' ' || __i__=
printf "${__i__}"'%s%s:ok%s' "${COLOR_OK_ON}" "${*}" "${COLOR_OK_OFF}"
TEST_ANY=1
}
t_echoerr() {
ESTAT=1
t_echo0err "${@}"
}
t_echo0err() {
[ -n "${TEST_ANY}" ] && __i__="\n" || __i__=
printf "${__i__}"'%sERROR: %s%s\n' \
"${COLOR_ERR_ON}" "${*}" "${COLOR_ERR_OFF}"
TEST_ANY=
}
t_echowarn() {
[ -n "${TEST_ANY}" ] && __i__=' ' || __i__=
printf "${__i__}"'%s%s%s' "${COLOR_WARN_ON}" "${*}" "${COLOR_WARN_OFF}"
TEST_ANY=1
}
t_echoskip() {
[ -n "${TEST_ANY}" ] && __i__=' ' || __i__=
printf "${__i__}"'%s%s[skip]%s' \
"${COLOR_WARN_ON}" "${*}" "${COLOR_WARN_OFF}"
TEST_ANY=1
TESTS_SKIPPED=`add ${TESTS_SKIPPED} 1`
}
check() {
restat=${?} tid=${1} eestat=${2} f=${3} s=${4} optmode=${5}
echo >&2 CHECK $TID 0
TESTS_PERFORMED=`add ${TESTS_PERFORMED} 1`
echo >&2 CHECK $TID 10
if [ -n "${CHECK}${RUN_TEST}" ]; then
x="t.${TEST_NAME}-${tid}"
echo >&2 CHECK $TID 11
if :; then
y=test-out
echo >&2 CHECK $TID 20
echo >&2 CHECK $TID 21
if [ -n "${y}" ]; then
echo >&2 CHECK $TID 22
if : ; then
echo >&2 CHECK $TID 22.5
# NOTE: REMOVE THIS (or use true(1)) AND WORKS directly and via bmake (mksh)
# (env -i regardless, "false" also is not it, whatever)
env -i ls -latr /NONEXISTENT
echo >&2 CHECK $SHELL $TID 22.8
# NOTE: monitor should be "on" here
set -o >&2
echo >&2 CHECK $TID 23
fi
echo >&2 CHECK $TID 30
fi
echo >&2 CHECK $TID 35
fi
fi
echo >&2 CHECK $TID 100
}
check_ex0() {
# $1=test name [$2=status]
__qm__=${?}
[ ${#} -gt 1 ] && __qm__=${2}
TESTS_PERFORMED=`add ${TESTS_PERFORMED} 1`
if [ ${__qm__} -ne 0 ]; then
ESTAT=1
t_echoerr "${1}: unexpected non-0 exit status: ${__qm__}"
TESTS_FAILED=`add ${TESTS_FAILED} 1`
else
t_echook "${1}"
TESTS_OK=`add ${TESTS_OK} 1`
fi
}
check_exn0() {
# $1=test name [$2=status]
__qm__=${?}
[ ${#} -gt 1 ] && __qm__=${2}
[ ${#} -gt 2 ] && __expect__=${3} || __expect__=
TESTS_PERFORMED=`add ${TESTS_PERFORMED} 1`
if [ ${__qm__} -eq 0 ]; then
ESTAT=1
t_echoerr "${1}: unexpected 0 exit status: ${__qm__}"
TESTS_FAILED=`add ${TESTS_FAILED} 1`
elif [ -n "${__expect__}" ] && [ ${__expect__} -ne ${__qm__} ]; then
ESTAT=1
t_echoerr "${1}: unexpected exit status: ${__qm__} != ${__expected__}"
TESTS_FAILED=`add ${TESTS_FAILED} 1`
else
t_echook "${1}"
TESTS_OK=`add ${TESTS_OK} 1`
fi
}
color_init() {
:
}
if ( [ "$((1 + 1))" = 2 ] ) >/dev/null 2>&1; then
add() {
echo "$((${1} + ${2}))"
}
else
add() {
${awk} 'BEGIN{print '${1}' + '${2}'}'
}
fi
if ( [ "$((2 % 3))" = 2 ] ) >/dev/null 2>&1; then
modulo() {
echo "$((${1} % ${2}))"
}
else
modulo() {
${awk} 'BEGIN{print '${1}' % '${2}'}'
}
fi
have_feat() {
( "${RAWMAILX}" ${ARGS} -X'echo $features' -Xx |
${grep} +${1}, ) >/dev/null 2>&1
}
t_X_errexit() {
t_prolog "${@}"
</dev/null ${MAILX} ${ARGS} -Snomemdebug \
-X'echo one' -X' echos nono ' -X'echo two' \
> ./t1 2>&1
echo >&2 PRE T1 CHEK
check 1 0 ./t1 '2700500141 51'
echo >&2 AFTER T1 CHEK
t_epilog "$@"
return
}
ssec=$SECONDS
jobreaper_start
jspawn X_errexit
jsync 1
jobreaper_stop
esec=$SECONDS
exit ${ESTAT}
# s-sh-mode
[-- Attachment #3: jobo.mk --]
[-- Type: text/plain, Size: 20 bytes --]
test:
./mx-test.sh
next reply other threads:[~2020-12-19 17:35 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-12-19 17:28 Steffen Nurpmeso [this message]
2020-12-19 22:21 ` dash 0.5.11.2, busybox sh 1.32.0, FreeBSD 12.2 sh: spring TTOU but should not i think Steffen Nurpmeso
2020-12-19 23:52 ` Harald van Dijk
2020-12-21 16:24 ` Jilles Tjoelker
2020-12-21 19:43 ` Steffen Nurpmeso
2020-12-23 20:18 ` Harald van Dijk
2020-12-24 15:29 ` Jilles Tjoelker
2021-01-10 23:56 ` Harald van Dijk
2021-01-06 4:46 ` Herbert Xu
2021-01-06 4:45 ` [PATCH] jobs: Block signals during tcsetpgrp Herbert Xu
2021-01-06 21:16 ` Harald van Dijk
2021-01-06 22:41 ` Jilles Tjoelker
2021-01-07 7:36 ` Denys Vlasenko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20201219172838.1B-WB%steffen@sdaoden.eu \
--to=steffen@sdaoden.eu \
--cc=dash@vger.kernel.org \
--cc=jilles@stack.nl \
--cc=vda.linux@googlemail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).