On Dec 27, 2012, at 4:41 PM, Jeff Hobbs wrote:
> On 2012-11-20, at 12:23 PM, Joe English <jenglish@...> wrote:
>> Andreas Kupries wrote:
>>> Karl Lehenbauer wrote:
>>>> Andreas Kupries wrote:
>>>>>> ::env() array
>>>>>> Per Joe English and others, the current behavior of this array is
>>>>>> unavoidably thread-unsafe. We need some way to access environment
>>>>>> variable values, though, so some other mechanism would have to be
>>>>>> defined. An [env] command, perhaps?
>>>> "env get", "env set", and "env unset"?
>>> No, I was actually thinking of behind-the-scenes magic for the copy
>>> operations in either direction, just done explicitly where needed
>>> instead of relying on a var-trace run every time something changes.
>>> The issue, I believe, is not that Tcl's and the system's view of the
>>> environment has to be in sync at certain places, but that we are
>>> currently using C-level variable tracing to perform the sync.
>>> What I propose is to make the sync more explicit in the C code, at the
>>> points needed.
>>> I do not propose to expose this to Tcl scripts.
>> I had in mind something more: Tcl should not try to keep
>> the "real" process environment in sync with 'env' at all --
>> that's the part that is nonthreadsafe, after all.
>> Instead, each interp should have its own $::env array,
>> initialized either from environ or from the contents
>> of the parent interp's ::env at the time of creation.
>> [exec], [open "|..."] et al. would pass the content
>> of the calling interp's ::env array as the third argument
>> to execve() or the seventh (?) argument to CreateProcess().
>> This also avoids a number of portability problems surrounding
>> putenv() / setenv() -- Tcl would simply never call them.
> I don't recall seeing Brian on this conversaiotn, but iirc he is just such a user, that expects to be able to reflect 3rd party library modifications to environ to be reflected in Tcl. I would support cleaning this up into a command. Possibly the edge cases could all be swept under a slower sync 'env sync' command?
The important features to maintain, in order of priority, are:
* [exec] needs to have current environment variables passed to the new process
* Use of system() or execve(), etc., from within the application or 3rd party shared libraries should expect to see the same environment variables visible/set from Tcl.
* Faster $env(...) would be really nice, avoiding possible WTF moments, but not a deal breaker.
What I don't see, at least in our applications, is the need to pass environment variable changes from C code to Tcl, at least not frequently enough that would warrant the need for $env() to constantly check. It seems reasonable to me for applications with embedded Tcl to either use Tcl_ versions of putenv()/getenv(), or have an explicit [env sync] command; it's quite likely it will be known at the tcl script level when env changes are expected from the application C code. (note: our application already has an [env] command, but it has nothing to do with environment variables. If [env] is added to Tcl, please consider putting it in a namespace, e.g., tcl::env)
I haven't done anything significant with threads & Tcl (our app is not threaded) to have any good insight on this aspect w.r.t. environment variables. But I suspect that using an explicit 'sync' command would be a reasonable approach.