Re: Until loop
[email protected] (James Taylor) Wed, 3 Apr 2002 12:14:34 +0100 (BST)
| Newsgroups | perl.riscos |
|---|---|
| Message-ID | <[email protected]> |
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