summaryrefslogtreecommitdiff
path: root/usr/src/lib/libshell
diff options
context:
space:
mode:
authorCasper H.S. Dik <Casper.Dik@Sun.COM>2009-02-13 18:28:51 +0100
committerCasper H.S. Dik <Casper.Dik@Sun.COM>2009-02-13 18:28:51 +0100
commit81af778e872fc2ec5f0ac36e7b25bdb24ebd2d6a (patch)
tree676e6d985d7467919454b04cff593561bc316419 /usr/src/lib/libshell
parent7c2ac4814b2e73c72798fe6d7b84ac8540fdd35b (diff)
downloadillumos-joyent-81af778e872fc2ec5f0ac36e7b25bdb24ebd2d6a.tar.gz
6793120 pkill fails on native and sn1 branded zones
6800929 snv_106 ksh93 update breaks Install(1M) Contributed by Roland Mainz <roland.mainz@nrubsig.org>
Diffstat (limited to 'usr/src/lib/libshell')
-rw-r--r--usr/src/lib/libshell/Makefile.demo3
-rw-r--r--usr/src/lib/libshell/common/include/defs.h1
-rw-r--r--usr/src/lib/libshell/common/sh/subshell.c6
-rw-r--r--usr/src/lib/libshell/common/sh/xec.c7
-rw-r--r--usr/src/lib/libshell/common/tests/sun_solaris_cr_6800929_large_command_substitution_hang.sh137
-rw-r--r--usr/src/lib/libshell/misc/ERRATA.txt71
6 files changed, 221 insertions, 4 deletions
diff --git a/usr/src/lib/libshell/Makefile.demo b/usr/src/lib/libshell/Makefile.demo
index fa8235af6e..f32a2c75b1 100644
--- a/usr/src/lib/libshell/Makefile.demo
+++ b/usr/src/lib/libshell/Makefile.demo
@@ -20,7 +20,7 @@
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -102,6 +102,7 @@ DEMOFILES= \
tests/sun_solaris_cr_6754020_weird_square_bracket_expansion.sh \
tests/sun_solaris_cr_6763594_command_failure_execs_twice.sh \
tests/sun_solaris_cr_6766246_pattern_matching_bug.sh \
+ tests/sun_solaris_cr_6800929_large_command_substitution_hang.sh \
tests/sun_solaris_getconf.sh \
tests/sun_solaris_local_compound_nameref001.sh \
tests/sun_solaris_staticvariables.sh \
diff --git a/usr/src/lib/libshell/common/include/defs.h b/usr/src/lib/libshell/common/include/defs.h
index 78263fefb8..f5e03fd98e 100644
--- a/usr/src/lib/libshell/common/include/defs.h
+++ b/usr/src/lib/libshell/common/include/defs.h
@@ -166,6 +166,7 @@ struct limits
char winch; \
char indebug; /* set when in debug trap */ \
unsigned char lastsig; /* last signal received */ \
+ char subshare; /* set when in ${..} comsub */ \
char *readscript; /* set before reading a script */ \
int *inpipe; /* input pipe pointer */ \
int *outpipe; /* output pipe pointer */ \
diff --git a/usr/src/lib/libshell/common/sh/subshell.c b/usr/src/lib/libshell/common/sh/subshell.c
index 75dfc1f97d..4d54449c27 100644
--- a/usr/src/lib/libshell/common/sh/subshell.c
+++ b/usr/src/lib/libshell/common/sh/subshell.c
@@ -89,6 +89,7 @@ static struct subshell
int coutpipe;
int cpipe;
int nofork;
+ char subshare;
} *subshell_data;
static int subenv;
@@ -477,7 +478,9 @@ Sfio_t *sh_subshell(Shnode_t *t, int flags, int comsub)
sp->bckpid = shp->bckpid;
if(comsub)
sh_stats(STAT_COMSUB);
- if(!comsub || (comsub==1 && !sh_isoption(SH_SUBSHARE)))
+ sp->subshare = shp->subshare;
+ shp->subshare = comsub==2 || (comsub==1 && sh_isoption(SH_SUBSHARE));
+ if(!comsub || !shp->subshare)
{
sp->shpwd = shp->pwd;
sp->pwd = (shp->pwd?strdup(shp->pwd):0);
@@ -677,6 +680,7 @@ Sfio_t *sh_subshell(Shnode_t *t, int flags, int comsub)
shp->cpipe[1] = sp->cpipe;
shp->coutpipe = sp->coutpipe;
}
+ shp->subshare = sp->subshare;
if(shp->subshell)
SH_SUBSHELLNOD->nvalue.s = --shp->subshell;
if(sp->sig)
diff --git a/usr/src/lib/libshell/common/sh/xec.c b/usr/src/lib/libshell/common/sh/xec.c
index a930c18460..1c93fa9dab 100644
--- a/usr/src/lib/libshell/common/sh/xec.c
+++ b/usr/src/lib/libshell/common/sh/xec.c
@@ -1406,7 +1406,12 @@ int sh_exec(register const Shnode_t *t, int flags)
pid_t savepgid = job.curpgid;
job.curpgid = 0;
if(shp->subshell)
- sh_subtmpfile(1);
+ {
+ if(shp->subshare)
+ sh_subtmpfile(0);
+ else
+ sh_subfork();
+ }
shp->inpipe = pvo;
shp->outpipe = pvn;
pvo[1] = -1;
diff --git a/usr/src/lib/libshell/common/tests/sun_solaris_cr_6800929_large_command_substitution_hang.sh b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6800929_large_command_substitution_hang.sh
new file mode 100644
index 0000000000..396095ee63
--- /dev/null
+++ b/usr/src/lib/libshell/common/tests/sun_solaris_cr_6800929_large_command_substitution_hang.sh
@@ -0,0 +1,137 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Test whether CR #6800929 ("snv_106 ksh93 update breaks Install(1M)") has been fixed.
+#
+# Quote from CR #6800929:
+# ---- snip ----
+# so i just upgraded this morning from snv_105 to snv_106. now
+# Install(1M) is hanging whenever i run it. i'm running it as follows:
+# Install -o debug -k i86xpv -T domu-219:/tmp
+#
+# and here's where it's hung:
+# ---8<---
+# xxxxx@xxxxx $ pstack 204600
+# 204600: /bin/ksh /opt/onbld/bin/Install -o debug -k i86xpv -T domu-219:/tmp
+# fffffd7fff2e3d1a write (1, 4154c0, 64)
+# fffffd7ffefdafc8 sfwr () + 2d0
+# fffffd7ffefc0f6f _sfflsbuf () + 217
+# fffffd7ffefcb9f7 sfsync () + 17f
+# fffffd7ffefc5c58 _sfphead () + 188
+# fffffd7ffefc5ef5 _sfpmove () + 55
+# fffffd7ffefc2595 _sfmode () + 22d
+# fffffd7ffefc5fb1 sfpool () + 99
+# fffffd7fff15eb8e sh_exec () + 2f56
+# fffffd7fff15f78c sh_exec () + 3b54
+# fffffd7fff15d9c8 sh_exec () + 1d90
+# fffffd7fff15788e sh_subshell () + 646
+# fffffd7fff134562 comsubst () + 8a2
+# fffffd7fff12f61f copyto () + bcf
+# fffffd7fff12df79 sh_macexpand () + 1f1
+# fffffd7fff1129f5 arg_expand () + a5
+# fffffd7fff112812 sh_argbuild () + 9a
+# fffffd7fff15dbe2 sh_exec () + 1faa
+# fffffd7fff15d854 sh_exec () + 1c1c
+# fffffd7fff0f22ef b_dot_cmd () + 507
+# fffffd7fff161559 sh_funct () + 199
+# fffffd7fff15ef35 sh_exec () + 32fd
+# fffffd7fff136e86 exfile () + 786
+# fffffd7fff136676 sh_main () + 7fe
+# 0000000000400e72 main () + 52
+# 0000000000400ccc ????
+# ---8<---
+#
+# there is only one place where Install(1M) invokes "uniq":
+# set -- `grep "^CONF" $modlist | sort | uniq`;
+#
+# as it turns out, i can easily reproduce this problem as follows:
+# ---8<---
+# xxxxx@xxxxx $ ksh93
+# xxxxx@xxxxx $ set -- `cat /etc/termcap | sort | uniq`
+# <hang>
+# ---8<---
+# ---- snip ----
+
+
+function err_exit
+{
+ print -u2 -n "\t"
+ print -u2 -r ${Command}[$1]: "${@:2}"
+ (( Errors+=1 ))
+}
+
+alias err_exit='err_exit $LINENO'
+
+integer Errors=0
+
+integer i j d
+typeset tmpfile
+
+# test 1: run loop and check various temp filesizes
+tmpfile="$(mktemp "/tmp/sun_solaris_cr_6800929_large_command_substitution_hang.${PPID}.$$.XXXXXX")" || err_exit "Cannot create temporary file."
+
+for (( i=1*1024 ; i <= 512*1024 ; i*=2 )) ; do
+ # Create temp file
+ {
+ for ((j=0 ; j < i ; j+=16 )) ; do
+ print "0123456789abcde"
+ done
+ } >"${tmpfile}"
+
+ # Run test child
+ ${SHELL} -c "builtin cat ; print -- \"\$(cat \"${tmpfile}\" | cat)\" ; true" >/dev/null &
+ (( childpid=$! ))
+
+ # wait up to log2(i) seconds for the child to terminate
+ # (this is 10 seconds for 1KB and 19 seconds for 512KB)
+ (( d=log2(i) ))
+ for (( j=0 ; j < d ; j++ )) ; do
+ kill -0 ${childpid} 2>/dev/null || break
+ sleep 0.5
+ done
+
+ if kill -0 ${childpid} 2>/dev/null ; then
+ err_exit "test1: child (pid=${childpid}) still busy, filesize=${i}."
+ kill -KILL ${childpid} 2>/dev/null
+ fi
+ wait # wait for child (and/or avoid zombies/slime)
+ rm "${tmpfile}"
+done
+
+
+# test 2: Edward's Solaris-specific testcase
+${SHELL} -c 'builtin uniq ; set -- `cat /etc/termcap | sort | uniq` ; true' >/dev/null &
+(( childpid=$! ))
+sleep 5
+if kill -0 ${childpid} 2>/dev/null ; then
+ err_exit "test2: child (pid=${childpid}) still busy."
+ kill -KILL ${childpid} 2>/dev/null
+fi
+wait # wait for child (and/or avoid zombies/slime)
+
+# tests done
+exit $((Errors))
diff --git a/usr/src/lib/libshell/misc/ERRATA.txt b/usr/src/lib/libshell/misc/ERRATA.txt
index f94d327dd3..f14a66a950 100644
--- a/usr/src/lib/libshell/misc/ERRATA.txt
+++ b/usr/src/lib/libshell/misc/ERRATA.txt
@@ -20,7 +20,7 @@
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -239,4 +239,73 @@ Index: src/lib/libshell/common/sh/jobs.c
/* check to see whether job status has been saved */
-- snip --
+
+######## Errata #004: ########
+A fix was backported to cure a hang in a command substitution when the
+amount of data exceeds a certain amount of data (this was causing
+the hang in CR #6800929 ("snv_106 ksh93 update breaks Install(1M)")).
+The following files have been changed:
+-- snip --
+Index: src/lib/libshell/common/include/defs.h
+===================================================================
+--- src/lib/libshell/common/include/defs.h (revision 1391)
++++ src/lib/libshell/common/include/defs.h (working copy)
+@@ -166,6 +166,7 @@
+ char winch; \
+ char indebug; /* set when in debug trap */ \
+ unsigned char lastsig; /* last signal received */ \
++ char subshare; /* set when in ${..} comsub */ \
+ char *readscript; /* set before reading a script */ \
+ int *inpipe; /* input pipe pointer */ \
+ int *outpipe; /* output pipe pointer */ \
+Index: src/lib/libshell/common/sh/subshell.c
+===================================================================
+--- src/lib/libshell/common/sh/subshell.c (revision 1391)
++++ src/lib/libshell/common/sh/subshell.c (working copy)
+@@ -89,6 +89,7 @@
+ int coutpipe;
+ int cpipe;
+ int nofork;
++ char subshare;
+ } *subshell_data;
+
+ static int subenv;
+@@ -477,7 +478,9 @@
+ sp->bckpid = shp->bckpid;
+ if(comsub)
+ sh_stats(STAT_COMSUB);
+- if(!comsub || (comsub==1 && !sh_isoption(SH_SUBSHARE)))
++ sp->subshare = shp->subshare;
++ shp->subshare = comsub==2 || (comsub==1 && sh_isoption(SH_SUBSHARE));
++ if(!comsub || !shp->subshare)
+ {
+ sp->shpwd = shp->pwd;
+ sp->pwd = (shp->pwd?strdup(shp->pwd):0);
+@@ -677,6 +680,7 @@
+ shp->cpipe[1] = sp->cpipe;
+ shp->coutpipe = sp->coutpipe;
+ }
++ shp->subshare = sp->subshare;
+ if(shp->subshell)
+ SH_SUBSHELLNOD->nvalue.s = --shp->subshell;
+ if(sp->sig)
+Index: src/lib/libshell/common/sh/xec.c
+===================================================================
+--- src/lib/libshell/common/sh/xec.c (revision 1391)
++++ src/lib/libshell/common/sh/xec.c (working copy)
+@@ -1406,7 +1406,12 @@
+ pid_t savepgid = job.curpgid;
+ job.curpgid = 0;
+ if(shp->subshell)
+- sh_subtmpfile(1);
++ {
++ if(shp->subshare)
++ sh_subtmpfile(0);
++ else
++ sh_subfork();
++ }
+ shp->inpipe = pvo;
+ shp->outpipe = pvn;
+ pvo[1] = -1;
+-- snip --
#EOF.