How to test for the absence of an infinite loop?
I've just found a bug in my module. The bug results in an inappropriate infinite loop. Before I fix the bug, I want to write up a test case. I can reproduce the bug OK, but if I put that code into the module tests, and the bug isn't fixed, or comes back for some reason, then the test program will go into an infinite loop. The test harness doesn't seem to notice that. I don't want to go sticking code into my test files that might cause an infinite loop and hang up the test harness or the entire system. If the module were for Unix only, I would stick an 'alarm 10' at the top of the test program. I'm told this won't work under Win32. What's the right way to handle this?
Re: How to test for the absence of an infinite loop?
Michael The Schwern <[EMAIL PROTECTED]> says: > Use alarm and skip the test if $Config{d_alarm} is false (see > t/op/alarm.t for an example). If you think the infinite loop is due > to a programming glitch, as opposed to a cross-platform issue, this > will be enough. Thanks very much! > The only other thing I can think of is to set up a parent process > which forks off a child ARRRGH. NO FORK. Actually that reminds me of another puzzle I have. My module provides an interface to 'flock'. What is an easy way to check that the file is actually being locked? I put off writing the tests because i did not want to fork. Is this mailing list the right place to ask "how do I test for X" questions? Or would the module-authors list be more appropriate?
Re: How to test for the absence of an infinite loop?
> I just thought of a clever way to do it without alarm! So clever, it doesn't work! > lock_file($foo); > open(FH, $foo); > ok( !flock(FH, LOCK_NB | LOCK_EX) ); Seriously, on most unix systems, the following: flock(FH, LOCK_EX); flock(FH, LOCK_EX|LOCK_NB) or die; doe *not* die. A process is allowed to ask for (and obtain) an exclusive lock on a file if it already has a lock on that same file. There's no deadlock at all. I just checked this under linux and solaris with: use Fcntl ':flock'; open F, "+< $0: or die $!; flock F, LOCK_EX or die $!; flock F, LOCK_EX|LOCK_NB or die $!; print "OK\n"; and it OK's on both. Similarly, use Fcntl ':flock'; open F, "+< $0" or die $!; open G, "+< $0" or die $!; flock F, LOCK_EX or die $!; flock G, LOCK_EX|LOCK_NB or die $!; print "OK\n"; This failus under Linux (which I think is wrong) but OK's on Solaris. "OK" here means "What you suggested won't work." > The traditional approaches require causing a deadlock and breaking it > with alarm. Perhaps the traditional approach doesn't work. :) > So here's the other way. We cause a deadlock using another process > which kills itself after a certain amount of time. > > my $start = time; > lock_file($foo); > system($^X, '-e', 'use Whatever; alarm 5; lock_file($foo)'); > cmp_ok( time, '>', $start + 3, 'Locking works' ); > > again, these all rely on alarm(). This on also relies on system creating a new process. I wasn't sure what this would do on Win32, VMS, OS390, etc. Hence my original question: >> What is an easy way to check that the file is actually being locked? >> I put off writing the tests because i did not want to fork. Sorry to be so elliptical. What I should have said was that I can think of lots of ways to do it but they all involve starting a new process, and I'm reluctant to start a new prcoess unless I have to, because I have no idea what it does on Weird Platform X.
O_ACCMODE
Supposing that Fcntl and O_RDONLY are known to be available, how likely is it that O_ACCMODE will also be available? Are there any platforms that have O_RDONLY but not O_ACCMODE?
Re: O_ACCMODE
> You probably already found out, but > > HP-UX 10.20 Has it defined as 003 > HP-UX 11.00 Has it defined as 003 > AIX 4.3.3.0 Has it defined as 3 > AIX 4.2.1.0 Has it defined as 3 Thanks for the information. It turns out some Win32 systems don't have it at all, so I have to avoid it. Instead, I'm doing: use Fcntl 'O_RDONLY', 'O_RDWR', 'O_WRONLY'; sub O_ACCMODE () { O_RDONLY | O_WRONLY | O_RDWR } which I think should work everywhere that defines O_((RD|WR)ONLY|RDWR), whatever their values.