8

I have function where I am expecting it to hang sometime. So I am setting one global variable and then reading it, if it didn't come up after few second I give up. Below is not complete code but it's not working as I am not getting $START as value 5

START=0
ineer()
{
    sleep 5
    START=5
    echo "done $START"   ==> I am seeing here it return 5
    return $START
}
echo "Starting"
ineer &

while true
do
    if [ $START -eq 0 ]
    then
        echo "Not null $START"  ==> But $START here is always 0
    else
        echo "else $START"
        break;
    fi
    sleep 1;
done
eswaat
  • 733
  • 1
  • 13
  • 31
  • 6
    I suspect that running the function in the background causes it to be executed in a subshell, so the variable changes are not reflected in the parent shell. – user000001 Apr 16 '15 at 17:33
  • timeout is exact fit for me but It did't take function as command – eswaat Apr 16 '15 at 17:35
  • 3
    You may be interested in http://unix.stackexchange.com/questions/87284/how-to-share-environment-variables-between-shells-like-globals-related-to-a-mast -- mind you, @user000001 is exactly right that `ineer` is executed in a subshell and doesn't share an environment with its parent shell, so what you're going to find there are workarounds (mostly involving files). – Wintermute Apr 16 '15 at 17:36
  • You might need to look at the `timeout` command from GNU coreutils. You may also end up looking at signals (`trap` and `kill`) between child and parent processes. – Jonathan Leffler Apr 16 '15 at 17:40

4 Answers4

12

You run inner function call in back ground, which means the START will be assigned in a subshell started by current shell. And in that subshell, the START value will be 5.

However in your current shell, which echo the START value, it is still 0. Since the update of START will only be in the subshell.

Each time you start a shell in background, it is just like fork a new process, which will make a copy of all current shell environments, including the variable value, and the new process will be completely isolate from your current shell.

Since the subshell have been forked as a new process, there is no way to directly update the parent shell's START value. Some alternative ways include signals passing when the subshell which runs inner function exit.

common errors:

export

export could only be used to make the variable name available to any subshells forked from current shell. however, once the subshell have been forked. The subshell will have a new copy of the variable and the value, any changes to the exported variable in the shell will not effect the subshell.

Please take the following code for details.

#!/bin/bash
export START=0
ineer()
{
    sleep 3
    export START=5
    echo "done $START"  # ==> I am seeing here it return 5
    sleep 1
    echo "new value $START"
    return $START
}
echo "Starting"
ineer &

while true
do
    if [ $START -eq 0 ]
    then
        echo "Not null $START" #  ==> But $START here is always 0
        export START=10
        echo "update value to $START"
        sleep 3
    else
        echo "else $START"
        break;
    fi
    sleep 1;
done
Community
  • 1
  • 1
Kun Ling
  • 2,211
  • 14
  • 22
2

The problem is that ineer & runs the function in a subshell, which is its own scope for variables. Changes made in a subshell will not apply to the parent shell. I recommend looking into kill and signal catching.

Politank-Z
  • 3,653
  • 3
  • 24
  • 28
1

Save pid of inner & by:

pid=$!

and use kill -0 $pid (that is zero!!) to detect if your process still alive.

But better redesign inner to use lock file, this is safer check!

UPDATE From KILL(2) man page:

  #include <sys/types.h>
  #include <signal.h>

  int kill(pid_t pid, int sig);

If sig is 0, then no signal is sent, but error checking is still
performed; this can be used to check for the existence
of a process ID or process group ID.
gavenkoa
  • 45,285
  • 19
  • 251
  • 303
-1

The answer is: in this case you can use export. This instruction allow all subprocesses to use this variable. So when you'll call the ineer function it will fork a process that is copying the entire environment, including the START variable taken from the parent process.

You have to change the first line from:

START=0

to:

export START=0

You may also want to read this thread: Defining a variable with or without export

Community
  • 1
  • 1
  • export does not work, as it does not effect the subshell once the subshell have already been forked. – Kun Ling Apr 16 '15 at 21:38