Jan Palus dixit: [ note from IRC, this is on PLD Linux ]
>project -- just made an observation in my Linux distribution of choice >which has mksh as /bin/sh. \o/ | / \ >1. Looking at the expression in a simplified form: > >OUT=$( ((echo foo; echo $? 1>&3) | :) 3>&1 ) && echo "$OUT" > >isn't it supposed to echo only 0? Yes. It does when you do… OUT=$( ( (echo foo; echo $? 1>&3) | :) 3>&1 ) && echo "$OUT" >Both mksh R51 and R52 echo foo and 0, This is a different bug in each. mksh R50 (which I have at hand right now) parses it like so… tg@herc:~ $ foo() { > OUT=$( ((echo foo; echo $? 1>&3) | :) 3>&1 ) && echo "$OUT" > } tg@herc:~ $ typeset -f foo foo() { OUT=$(( echo foo ; echo $? >&3 | : ) 3>&1 ) && echo "$OUT" } … which is a bug in the code that converts $((…)…) from parsing $((…)) to $(…) and has been fixed in R52. But mksh R52 has a different bug: tglase@tglase:~ $ foo() { > OUT=$( ((echo foo; echo $? 1>&3) | :) 3>&1 ) && echo "$OUT" > } tglase@tglase:~ $ typeset -f foo foo() { OUT=$({ ( echo foo ; echo $? >&3 | : ) ; } 3>&1 ) && echo "$OUT" } Correct parsing would look like this: tglase@tglase:~ $ bar() { > OUT=$( ( (echo foo; echo $? 1>&3) | :) 3>&1 ) && echo "$OUT" > } tglase@tglase:~ $ typeset -f bar bar() { OUT=$(( ( echo foo ; echo $? >&3 ) | : ) 3>&1 ) && echo "$OUT" } Now we have a timing issue though: tglase@tglase:~ $ OUT=$(( ( echo foo ; echo $? >&3 ) | : ) 3>&1 ) && echo "$OUT" 0 tglase@tglase:~ $ OUT=$(( ( echo foo ; echo $? >&3 ) | : ) 3>&1 ) && echo "$OUT" tglase@tglase:~ $ OUT=$(( ( echo foo ; echo $? >&3 ) | : ) 3>&1 ) && echo "$OUT" 0 tglase@tglase:~ $ OUT=$(( ( echo foo ; echo $? >&3 ) | : ) 3>&1 ) && echo "$OUT" tglase@tglase:~ $ OUT=$(( ( echo foo ; echo $? >&3 ) | : ) 3>&1 ) && echo "$OUT" 0 tglase@tglase:~ $ OUT=$(( ( echo foo ; echo $? >&3 ) | : ) 3>&1 ) && echo "$OUT" 0 tglase@tglase:~ $ OUT=$(( ( echo foo ; echo $? >&3 ) | : ) 3>&1 ) && echo "$OUT" tglase@tglase:~ $ OUT=$(( ( echo foo ; echo $? >&3 ) | : ) 3>&1 ) && echo "$OUT" 0 The problem here is that : returns immediately, so the 3>&1 and the end of the command substitution may not catch the $? echo’d any more. The following code is more reliable: tglase@tglase:~ $ OUT=$(( ( echo foo ; echo $? >&3 ) | sleep 1 ) 3>&1 ) && echo "$OUT" 0 >2. In original command large_git produces lots of output to stdout, >which as described above lands in $OUT both in R51 and R52, but here's >the awkward difference between the two: > >OUT="diff --git" >test "$OUT" -eq 141 && echo equals || echo not equals Oh no, you don’t compare strings numerically please. But this is also a bug that has been fixed in R52. >Looks like R51 passed git tests only by accident. Nah, the real cause for the problems here is that the git tests are broken (replace the “:” with a “sleep 1” to fix it), plus a parse problem in mksh (which I’ll fix in R52b now that I know about it). bye, //mirabilos -- This space for rent.