0

I am working on a script that goes:

#script_1.sh
function a() {
    export var1='...some calculations on $@...';
}

function b() {
    a "$@"
    local loc_b=$var1
}

function c() {
    a "$@"
    local loc_c=$var1
}

#script_2.sh
source script_1.sh
b val1 &
c val2 &
b val2 &

function a has getopt command and parses parameters for b and c. This has been simplified to a great extent.

When I call function b, function c and function b again at the end as background processes, I worry that I might have a race condition on assigning the exported var1 variable to the local variable.

  1. If I can guarantee that calls to function b or function c will be as background processes, do I have to worry about the race condition here?

  2. If there is no race, can I get away by not declaring the local variables for each function?

tabs_over_spaces
  • 352
  • 1
  • 3
  • 14
  • `export` doesn't do anything of value here: You can export values only to your children, not to your parent or your siblings. (A subshell that exports a value and then exits, then, simply throws that value away). – Charles Duffy Sep 27 '18 at 22:33
  • 1
    It's very tempting to flag this a duplicate of [bash background process modify global variable](https://stackoverflow.com/questions/13207292/bash-background-process-modify-global-variable), insofar as the information conveyed in that question and its answers moots/conveys everything relevant here. – Charles Duffy Sep 27 '18 at 22:34
  • Great share. I have the concepts of `environment`, `subshell` and `globals` confused. Correct me if this is wrong: 1. For a `function a` calling `function b`, we don't need to use `export` as it will be the same process. 2. `function a` called in background will inherit environment of it's parent (including all variables exported up to the function call). – tabs_over_spaces Sep 27 '18 at 23:06
  • Both (1) and (2) are correct. (And you don't even always need `export` for children -- a true subshell is a `fork()` with no `execve()`, but you only need to export a variable to put it in the environment if you need it to survive an `exec`-family call). – Charles Duffy Sep 27 '18 at 23:08

1 Answers1

3

Each background process gets its own copy of the environment. Child process can't change the environment of its parent process. So, there's no race condition: if you change a global variable before running a background process, the process will get the new value copied. If you run a background process before changing the value, the process will see the old value.

#!/bin/bash

global=1

inc () {
    ((++global))
    echo inc: $global
}

dec () {
    ((--global))
    echo dec: $global
}

inc & dec &
# 2   0

global=10
inc & dec & inc & dec &
# 11  9     11    9
choroba
  • 231,213
  • 25
  • 204
  • 289