Posted on 2007-01-09 18:49:21-08 by scunacc
Sharing (or not) %ENV

Hi all,

I have a threaded app where, each thread invokes other processes (I know - already dead in the water but bear with me).

For the moment I'm using qx, tho' I could also use any one of the open derivatives with pipes or open2/3 semantics or whatever.

Anyhow, in the thread, I want to set an env var specific to that thread that will condition how the subprocess invoked from it runs.

Now, I can - in the thread - set, e.g.

$ENV{RUN_DIR} = "/run_dirs/$tid";

...and, if I look at that - per thread it's indeed changing *some* copy of %ENV - I can even lock it and see the changes between threads. But, when I call qx in the thread, the %ENV (or at least, the inherited environment) is that of the *parent* thread before any threads were started.

Can anyone suggest a way to do this? I saw the article about cwd which confirmed what I was seeking to do that I was doing something like that - but no dice.

My only other current solution is to do something like this:

my $env = qq(export A=$A C=$C E=$E); # etc my $cmd = qq(some external command); my $result = qx($env ; $cmd);

which works.

This tripped me up moving from a non-threaded app to a threaded version. The non-threaded one of course inherits the environment changes in qx just fine.

Kind regards

Derek Jones.

" What a tangled web we weave when of threads we do conceive...."

Direct Responses: 4008 | Write a response
Posted on 2007-01-10 15:49:53-08 by jdhedden in response to 4002
Re: Sharing (or not) %ENV
This is not a 'threads-shared' module problem. It is a Perl bug. %ENV is not a shared variable. It is copied into each thread. The bug is that when 'qx/system' is run in a thread, it does not use %ENV for that thread, but rather %ENV from the main thread. The following illustrates this clearly:
#!/usr/bin/perl use strict; use warnings; $| = 1; use threads; $ENV{'MAIN'} = 'ENV{MAIN} set in main thread'; system('echo MAIN: $MAIN'); system('echo MAIN: $THRD --- this should be blank'); print("\n"); threads->create(sub { system('echo THRD: $MAIN'); $ENV{'THRD'} = 'ENV{THRD} set in child thread'; system('echo THRD: $THRD -- this should NOT be blank'); })->join(); print("\n"); system('echo MAIN: $MAIN'); system('echo MAIN: $THRD --- this should be blank');
which produces:
MAIN: ENV{MAIN} set in main thread MAIN: --- this should be blank THRD: ENV{MAIN} set in main thread THRD: -- this should NOT be blank MAIN: ENV{MAIN} set in main thread MAIN: --- this should be blank
I'll submit a 'perlbug' report on this. In the interim, you'll need to use the workaround you developed.
Direct Responses: Write a response
Perl Weekly newsletter
A free weekly newsletter for people who are busy to read all the blogs. click here to check it out.