Infinite Loop?

grantm on 2007-08-02T09:19:27

Here's some behaviour that surprised me. I would expect this program to loop forever:

#!/usr/bin/perl

use strict;
use warnings;

my $file1 = './test_file_1';
my $file2 = './test_file_2';

my $count = 1;
while(1) {
    unlink($file1);                      # create first file
    open(FILE, ">$file1");
    close(FILE);

    my $t0 = (stat($file1))[9];          # wait
    while(time() <= $t0) {
        sleep 1;
    }
    my $t1 = time();

    unlink($file2);                      # create second file
    open(FILE, ">$file2");
    close(FILE);

    if((stat($file2))[9] <= (stat($file1))[9]) {
        die sprintf(
            "Timestamps: %u %u  t0: %u t1: %u\n", 
            (stat($file2))[9], (stat($file1))[9], $t0, $t1
        );
    }
    printf("Loop count = %u\n", $count++);
}

Given that test_file_2 is not created until the system clock is greater than the modification time on test_file_1, I would expect that the die statement would never be reached. In fact, it fails for me on multiple systems after running for a small number of minutes.

My test systems are all running Linux, and using local filesystems. I have seen this sort of funky effect when using network filesystems, presumably due to clock drift between client and fileserver. I've also run into problems where updating a file on a local NTFS partition under Windows would either not update the time or would update it to have an earlier value.

This came up because Andreas Koenig did some extensive testing to highlight random failures in XML::Simple's text suite. Now that I know it's the test itself that's at fault I just need to make it a bit more robust.


Time != time

srezic on 2007-08-07T07:46:46

I can reproduce the behaviour also on FreeBSD. In a FreeBSD mailing list I found an explanation on the precision of time handling. The interesing part is:

Another problem with file times is that they can be older than the time at which they are made, due to shortcuts in time_second and getnanotime(). E.g., if the current time is N.009999 seconds so that time(3) returns N, then time_second may be (N-1) seconds, so file times may be 1 second older than the time at which they were made if vfs.timestamp_precision is the default.
This seems to be exactly the problem you had. In FreeBSD, there's the possibility to set the precision of filesystem timestamps to microseconds or nanoseconds (instead of just seconds). If I do so and re-run the script, then the problem does not occur, at least for 10000 iterations (formerly ~400 iterations were enough).

Re:Time != time

grantm on 2007-08-07T21:27:44

Interesting. It sounds like something I just need to learn to live with :-)