ATF-devel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: ATF confusion with improperly terminated script



On Sun, Feb 6, 2011 at 2:40 PM, Jilles Tjoelker <jilles%stack.nl@localhost> 
wrote:
> On Sun, Feb 06, 2011 at 02:04:21PM -0800, Garrett Cooper wrote:
>>     Close, but not quite. The issue is scope [and/or whether or not
>> it's executing the functions in a subshell?], and it's something that
>> I didn't realize before now. Note that magically everything works
>> within the scope of the function, but outside of foo(), bar() and
>> baz() aren't visible. So that's why the ATF functions work in the
>> script I attached earlier, but filters out the nested functions when
>> it checks for the testcases, whereas the standalone functions executed
>> without complaint. Guess that's what I get for trying to be foolishly
>> clever.
>>     AFAICT POSIX doesn't have anything to say on the subject of
>> function scope (probably because no one thought someone would abuse
>> function nesting), but the inability to execute nested functions in my
>> clever manner appears to be consistent behavior with FreeBSD's ash and
>> bash at least, so slap on the wrist for me :). It's interesting how
>> bash barfs on the eval'ed command, but that's purely an `academic'
>> observation.
>>     So, I guess I'll use some Makefile-fu to produce the testcases instead.
>
>> PS. The end-result is the same when you change the eval below into a
>> bareword function definition, but the symptoms up to that point are a
>> wee bit different.
>
>> $ cat ~/test_something.sh
>> #!/bin/sh
>>
>> echo "hello ${1:-world}; my pid is: $$"
>>
>> type bar baz foo
>>
>> foo() {
>>     eval "bar() { $_ $0 bar; }"
>>     baz() { $_ $0 baz; bar; }
>>     baz
>> }
>>
>> type bar baz foo
>>
>> if [ $# -eq 0 ]; then
>>     foo
>> fi
>
> POSIX says what should happen here, although it may not be as clear as
> you'd like. See XCU 2.9.5 Function Definition Command.
>
> How it works is that a function definition is a command that installs a
> function when executed. This is also pretty much the only way it can
> work given sh's parse-execute model. For example, if a user types a
> function definition at the command line, it is available for subsequent
> commands, until removed using 'unset -f'. The model is a set of defined
> functions, independent of their source code location.
>
> This also allows things like:
>
>        if [ need to use method1 ]; then
>                f() { ... method1 ...; }
>        else
>                f() { ... method2 ...; }
>        fi
>
> If you wrap this into a new function, you have a possibly useful use of
> nested function definitions. Note that there is no "scope" to speak of.
>
> Somewhat related, I consider calling a function from command
> substitution a somewhat questionable practice. Although it looks very
> much like a function that returns a string in other languages, it will
> run the function in a subshell environment. This is slower and prevents
> side effects.
>
> You can return arbitrary data via variables, either using a fixed
> variable name such as REPLY or having the caller pass in a variable name
> to write the result into.

Jilles's response is above.
Thanks!
-Garrett


Home | Main Index | Thread Index | Old Index