Re: AIX and Interix also do early PID recycling.
On 07/29/2012 12:46 AM, Chet Ramey wrote: > On 7/27/12 9:50 AM, Michael Haubenwallner wrote: > >> With attached patch I haven't been able to break the testcase below so far >> on that AIX 6.1 box here. >> >> But still, the other one using the $()-childs still fails. > > Try the attached patch for that. Collecting the patches and cleaning up now unused code, attached patch seems to fix both CHILD_MAX related problems on that AIX box here now, without using the RECYCLES_PIDS workaround. Thank you! /haubi/ Bash assumes pids aren't reused before sysconf(_SC_CHILD_MAX) immediate childs (the dynamic value), as well as ascending and wrapped around pid values. However, as specified by POSIX, conforming kernels actually guarantee for CHILD_MAX imediate childs (the static value) before reusing pids. Additionally, AIX (at least) does not guarantee for ascending pid values at all. Actually, AIX reuses pids after its CHILD_MAX value of 128 in somewhat random order in some configuration- or load-cases, resulting in race conditions like these: http://lists.gnu.org/archive/html/bug-bash/2008-07/msg00117.html This looks like a similar problem with Cygwin, where RECYCLES_PIDS is defined as the workaround, but that isn't really correct for AIX (and maybe Interix): http://www.cygwin.com/ml/cygwin/2004-09/msg00882.html http://www.cygwin.com/ml/cygwin/2002-08/msg00449.html *** jobs.c.orig 2012-08-20 16:23:51 +0200 --- jobs.c 2012-08-20 16:51:36 +0200 *** *** 317,324 static char retcode_name_buffer[64]; - /* flags to detect pid wraparound */ - static pid_t first_pid = NO_PID; - static int pid_wrap = -1; - #if !defined (_POSIX_VERSION) --- 317,320 *** *** 347,352 { js = zerojs; - first_pid = NO_PID; - pid_wrap = -1; } --- 343,346 *** *** 1823,1833 as the proper pgrp if this is the first child. */ - if (first_pid == NO_PID) - first_pid = pid; - else if (pid_wrap == -1 && pid < first_pid) - pid_wrap = 0; - else if (pid_wrap == 0 && pid >= first_pid) - pid_wrap = 1; - if (job_control) { --- 1817,1820 *** *** 1863,1875 #endif ! if (pid_wrap > 0) ! delete_old_job (pid); ! #if !defined (RECYCLES_PIDS) ! /* Only check for saved status if we've saved more than CHILD_MAX ! statuses, unless the system recycles pids. */ ! if ((js.c_reaped + bgpids.npid) >= js.c_childmax) ! #endif ! bgp_delete (pid); /* new process, discard any saved status */ last_made_pid = pid; --- 1850,1856 #endif ! delete_old_job (pid); ! bgp_delete (pid); /* new process, discard any saved status */ last_made_pid = pid; *** execute_cmd.c.orig 2012-08-20 16:36:10 +0200 --- execute_cmd.c 2012-08-20 16:51:14 +0200 *** *** 742,748 /* XXX - this is something to watch out for if there are problems ! when the shell is compiled without job control. */ ! if (already_making_children && pipe_out == NO_PIPE && ! last_made_pid != last_pid) { stop_pipeline (asynchronous, (COMMAND *)NULL); --- 742,750 /* XXX - this is something to watch out for if there are problems ! when the shell is compiled without job control. Don't worry about ! whether or not last_made_pid == last_pid; already_making_children ! tells us whether or not there are unwaited-for children to wait ! for and reap. */ ! if (already_making_children && pipe_out == NO_PIPE) { stop_pipeline (asynchronous, (COMMAND *)NULL);
Re: bash does filename expansion when assigning to array member in compound form
Am Sat, 18 Aug 2012 19:55:17 +0100 schrieb Stephane Chazelas: > 2012-08-18 10:26:22 -0500, Dan Douglas: >> This is a feature that all shells with this style of compound >> assignment have in common. If no explicit subscripts are given, the >> text between the parentheses is processed exactly as though it were >> arguments to a command including brace expansion, word-splitting, and >> pathname expansion (and consequently, quoting is just as important). >> This is an important feature because it allows storing the results of a >> glob in an array easily. >> >> If a subscript is given explicitly, then the right-hand side of the >> assignment is treated exactly as an ordinary scalar assignment would >> be, including all analagous behaviors for `+=' and the integer >> attribute. >> >> $ set -x; a=( [1]=* ) >> + a=([1]=*) > [...] > > Nope: > > ~/1$ touch '[1]=x' > ~/1$ bash -c 'a=( [1]=* ); echo "${a[@]}"' [1]=x ~/1$ bash -c 'a=( > [1]=asd ); echo "${a[@]}"' > asd > > That's a bug though. > I'm not sure if I got it right. Please correct me if I got it wrong: It is not generally a bug that Bash does filename expansion when assigning to array members in compound form. Only if explicit indices identify array members in a compound assignment there should be no filename expansion and it's a bug if Bash does so. Gundi
Re: bash does filename expansion when assigning to array member in compound form
On 08/20/2012 07:12 PM, Gundi Cress wrote: Am Sat, 18 Aug 2012 19:55:17 +0100 schrieb Stephane Chazelas: 2012-08-18 10:26:22 -0500, Dan Douglas: This is a feature that all shells with this style of compound assignment have in common. If no explicit subscripts are given, the text between the parentheses is processed exactly as though it were arguments to a command including brace expansion, word-splitting, and pathname expansion (and consequently, quoting is just as important). This is an important feature because it allows storing the results of a glob in an array easily. If a subscript is given explicitly, then the right-hand side of the assignment is treated exactly as an ordinary scalar assignment would be, including all analagous behaviors for `+=' and the integer attribute. $ set -x; a=( [1]=* ) + a=([1]=*) [...] Nope: ~/1$ touch '[1]=x' ~/1$ bash -c 'a=( [1]=* ); echo "${a[@]}"' [1]=x ~/1$ bash -c 'a=( [1]=asd ); echo "${a[@]}"' asd That's a bug though. I'm not sure if I got it right. Please correct me if I got it wrong: It is not generally a bug that Bash does filename expansion when assigning to array members in compound form. Only if explicit indices identify array members in a compound assignment there should be no filename expansion and it's a bug if Bash does so. Gundi And how would you achieve to fill array with all file names containing `[1]=' for example. Definitely it's good, if you want to be sure, to always quote all characters which means pathname expansion - `*', `?' and `['. RR
Re: bash does filename expansion when assigning to array member in compound form
On Monday, August 20, 2012 07:44:51 PM Roman Rakus wrote: > And how would you achieve to fill array with all file names containing > `[1]=' for example. $ ls [1]=a [1]=b $ ( typeset -a a=( \[1\]=* ); typeset -p a ) typeset -a a=('[1]=a' '[1]=b') $ ( typeset -a a=( [1]=* ); typeset -p a ) typeset -a a=([1]='*') $ In ksh93, by escaping. I think this is what most people would expect and probably what Bash intended. Of course, In that shell in order to use "[n]="-style indexing each and every element needs to be specified that way explicitly. I like that Bash can just implicitly start counting at any index. -- Dan Douglas
Re: bash does filename expansion when assigning to array member in compound form
2012-08-20 19:44:51 +0200, Roman Rakus: [...] > And how would you achieve to fill array with all file names > containing `[1]=' for example. [...] Another interesting question is how to fill the array with all the file names that start with a digit followed by "=". $ touch {3..5}=foo $ ls 3=foo 4=foo 5=foo $ bash -c 'a=([0-9]=*); typeset -p a' bash: [0-9]=*: bad array subscript declare -a a='()' $ bash -c 'shopt -s extglob; a=(@([0-9])=*); typeset -p a' bash: -c: line 0: syntax error near unexpected token `(' bash: -c: line 0: `shopt -s extglob; a=(@([0-9])=*); typeset -p a' $ bash -c 'shopt -s extglob a=(@([0-9])=*); typeset -p a' declare -a a='([0]="3=foo" [1]="4=foo" [2]="5=foo")' > Definitely it's good, if you want to be sure, to always quote all > characters which means pathname expansion - `*', `?' and `['. [...] Yes, the problem here is that "[" is overloaded in a conflicting manner as a globbing operator and that poorly designed special type of array assignment. Quoting them will prevent both, it become more tricky if you want only one or the other. Note that in bash that also means we need to quote variables in there even if IFS is set to "". $ bash -c 'a="*"; b=([1]=$a); typeset -p b' declare -a b='([0]="[1]=bar")' -- Stephane