On Mon 01 Apr, Richard Torrens (RiscOS) wrote:
> 
> In article <[EMAIL PROTECTED]>,
> Nicholas Clark <[EMAIL PROTECTED]> wrote:
> > 
> > On Mon, Apr 01, 2002 at 09:47:49AM +0100,
> > Richard Torrens (RiscOS) wrote:
> > > 
> > > Can anyone tell me why the following gets stuck?
> > > 
> > > until ($ENV{'BlackHole$BinDir'} eq "") {
> > >   system ('Unset BlackHole$BinDir');
> > > }
> > > 
> > > It gets stuck in a loop as if the test is only tested once.
> > 
> > From memory, I think that's pretty close to what actually happens.
> > I think that perl is actually caching things as they get read in %ENV.

Yes, I've just tested this and it looks like Perl populates
each entry in %ENV as you first read from it and then caches
it assuming that this will not change unless you explicitly
do so through the %ENV mechanism. As you said, saying

    delete $ENV{'varname'}

is the correct way to unset a system variable so that %ENV stays
in synch. This caching behaviour is presumptuous of the environment
being Unix-like, ie. private to the process rather than shared
between all processes as it is on most other OSes. I think this
behaviour should be considered a bug because even on a Unix
system you might wish to be able to read environment variables
that were exported by a child process. It should certainly be
fixed on ports to OSes with global environment variables.

> > Try this
> > 
> >   delete $ENV{'BlackHole$BinDir'};
> > 
> > in place of the loop. I think it should work (not in a position to
> > test it right now) as I think it will punch out to the real RISC OS
> > environment and delete it there (with no error if it never was there
> > in the first place)

Yes, it works exactly as you (Nick) expected. In addition, while a
particular %ENV entry does not exist, the %ENV mechanism always
reads from the OS and does not use a cached empty value. So
although Richard cannot use %ENV to spot when a variable becomes
*unset*, he could wait for a variable to be *set* for the first
time with something as simple as:

    sleep 1 until $ENV{'Blackhole$Finished'};


Richard Torrens (RiscOS) wrote:
> 
> Yes. Unfortunately I'm not really trying to merely unset a SysVar here.
[snip]
> I am really trying to test when this deletion has finished as during
> deletions BlackHole is single tasking and the network won't then
> respond work. So after this has terminated I want to feed a signal to
> the loop to release it.

If your Perl program is running in a taskwindow on the same
machine as the Slackhole it's waiting for then it won't get
control back until Blackhole has finished its single tasking.
All you need is something like:

    system 'Filer_Run ADFS::HD5.$.DataApps.!BlakHole2' and die $!;
    sleep 1; # To give the Wimp time to respond to the Filer_Run
    # Blackhole now does its thing single tasking
    # Now we've got control back so the backup process can continue

What's wrong with that? When I suggested it before, you seemed
quite positive about the idea. What's changed?

> Setting an Env variable seemed sensible. But not
> if the until {} loop won't read it.

Well, if all else fails you can of course just talk to RISC OS
directly by using a kernelswi call. Here is a subroutine that
will read any type of system variable directly:

sub readvarval ($) {
    my $name = shift;
    my ($regs, $buffer, $len);

    $buffer = "\0" x 1024; # Max length of buffer
    $regs = kernelswi('OS_ReadVarVal', $name, $buffer, length $buffer, 0, 3);
    return '' unless defined $regs; # Var not found or buffer overflow
    $len = (unpack 'i*', $regs)[1]; # R1 = length of string value
    return unpack "a$len", $buffer;
}

You will also need to say "use RISCOS::SWI;" at the top of your script.

-- 
James Taylor <[EMAIL PROTECTED]>
Based in Southam, Cheltenham, UK.
PGP key available ID: 3FBE1BF9
Fingerprint: F19D803624ED6FE8 370045159F66FD02

Reply via email to