Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

making sure a file is not currently being written to

by why_bird (Pilgrim)
on Jun 05, 2008 at 13:37 UTC ( [id://690425]=perlquestion: print w/replies, xml ) Need Help??

why_bird has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks

I have a file which is being written by a sub in one module, let's call it Write() in Write.pm. My script then later calls &Check() in Check.pm which opens that same file, runs through it and performs a series of checks on each line to make sure everything is in order. However, I think the file is still being written when I call &Check() since for a line near the end of the file I keep getting the error

Argument "1.21633032597832 + 1.8765165060" isn't numeric in numeric lt + (<) at Check.pm line x, <CONFIG> line y.

The line should read '1.21633032597832 + 1.8765165060i and indeed it does when I open and check the config file. There are also hundreds of lines almost identical to this one and they don't cause a problem (there's a regex to capture imaginary numbers to divert them away from the numerical comparison mentioned in the error). This problem also goes away when I insert sleep(3) between &Write() and &Check()

So..

  • Is there a way to tell whether the file is still being written?
  • Does it sound like this is the problem or could there be something I'm overlooking?
I've tried fiddling around and repeatedly inserting stat() and sleep(), but that doesn't seem to report any difference between when the file is still being written (I get this error) and when it's finished writing. I'm expicitly close()ing my filehandles at the end of the &Write() and &Check(), though they should be closed implicitly anyway, shouldn't they, since they go out of scope? (I naïvely thought that the close would wait till they're finished writing..)

Sorry for the rather rambling question, this is a problem that's caught me out a few times in various projects so it'd be good to figure it out

Cheers
why_bird
........
Those are my principles. If you don't like them I have others.
-- Groucho Marx
.......

Replies are listed 'Best First'.
Re: making sure a file is not currently being written to
by moritz (Cardinal) on Jun 05, 2008 at 13:43 UTC
    though they should be closed implicitly anyway, shouldn't they,

    Only if you use lexical variables as file handles. If you use open HANDLE, '>', $file;, then HANDLE is a global that doesn't go out of scope.

    When a file is closed, it should be written to disk immediately (well, the OS can still cache it, but it has to do it transparently).

    What you describe here should never happen, so if you can reproduce this behaviour in a small, self-contained script, please file a bug report.

      This can easily happen when Perl buffers some data instead of flushing it to disk. A second file handle opened to a file can't see that buffered data. Your solution of using lexical filehandles won't solve every case, for example the following:

      sub write_stuff { open my $fh, '>>', $logfilename or die "Can't append to '$logfilen +ame': $!"; ... check_stuff(); ... }; sub check_stuff { open my $fh, '<', $logfilename or die "Can't read '$logfilename': +$!"; while (<$fh>) { ... }; };

      (also see Suffering From Buffering)

        If one of your example functions calls the other, or threads are being used, that might happen, yes. If not, it's not allowed to happen.

        From perldoc -f close:

        Closes the file or pipe associated with the file handle, returning true only if IO buffers are successfully flushed and closes the system file descriptor.

        So if the closing was successfully (and it usually is, unless the disk is full or something really evil happens), the buffer has to be flushed. If not, it's a bug.

      Only if you use lexical variables as file handles. If you use open HANDLE, '>', $file;, then HANDLE is a global that doesn't go out of scope.

      Ah, I didn't realise this, thank you (I'm not yet quite on top of typeglobs(?)). In reality there are a lot of different subs writing to that file---I thought I had checked them all for terminating close()s, but perhaps I've missed one... What I'm doing should be fairly simple, so I doubt I've found a long hidden bug.. much more likely to be a mistake on my part. I'll check it out :)

      thanks

      ........
      Those are my principles. If you don't like them I have others.
      -- Groucho Marx
      .......
Re: making sure a file is not currently being written to
by Gangabass (Vicar) on Jun 05, 2008 at 14:52 UTC

    You can try to use flock() to lock file.

Re: making sure a file is not currently being written to
by Anonymous Monk on Jun 06, 2008 at 08:21 UTC
    open some.temporary write some.temporary close some.temporary rename some.temporary CONFIG

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://690425]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others rifling through the Monastery: (4)
As of 2024-03-29 08:02 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found