<p>What is the best way to create a lock on a file in Perl?</p>

<p>Is it best to flock on the file or to create a lock file to place a lock on and check for a lock on the lock file?</p>

[{'answer_id': 34928, 'author': 'mk.', 'author_id': 1797, 'author_profile': 'https://Stackoverflow.com/users/1797', 'pm_score': 0, 'selected': False, 'text': '<p>Use the <a href="http://perldoc.perl.org/functions/flock.html" rel="nofollow noreferrer">flock</a> Luke. </p>\n\n<p><strong>Edit:</strong> <a href="http://www.perlmonks.org/?node_id=7058" rel="nofollow noreferrer">This</a> is a good explanation.</p>\n'}, {'answer_id': 34929, 'author': 'Michael Ratanapintha', 'author_id': 1879, 'author_profile': 'https://Stackoverflow.com/users/1879', 'pm_score': 0, 'selected': False, 'text': "<p>flock creates Unix-style file locks, and is available on most OS's Perl runs on.  However flock's locks are advisory only.</p>\n\n<p>edit: emphasized that flock is portable</p>\n"}, {'answer_id': 34933, 'author': 'Chris Bunch', 'author_id': 422, 'author_profile': 'https://Stackoverflow.com/users/422', 'pm_score': 6, 'selected': True, 'text': '<p>If you end up using flock, here\'s some code to do it:</p>\n\n<pre><code>use Fcntl \':flock\'; # Import LOCK_* constants\n\n# We will use this file path in error messages and function calls.\n# Don\'t type it out more than once in your code.  Use a variable.\nmy $file = \'/path/to/some/file\';\n\n# Open the file for appending.  Note the file path is quoted\n# in the error message.  This helps debug situations where you\n# have a stray space at the start or end of the path.\nopen(my $fh, \'&gt;&gt;\', $file) or die "Could not open \'$file\' - $!";\n\n# Get exclusive lock (will block until it does)\nflock($fh, LOCK_EX) or die "Could not lock \'$file\' - $!";\n\n# Do something with the file here...\n\n# Do NOT use flock() to unlock the file if you wrote to the\n# file in the "do something" section above.  This could create\n# a race condition.  The close() call below will unlock the\n# file for you, but only after writing any buffered data.\n\n# In a world of buffered i/o, some or all of your data may not \n# be written until close() completes.  Always, always, ALWAYS \n# check the return value of close() if you wrote to the file!\nclose($fh) or die "Could not write \'$file\' - $!";\n</code></pre>\n\n<p>Some useful links:</p>\n\n<ul>\n<li><a href="http://www.perlmonks.org/?node_id=7058" rel="noreferrer">PerlMonks file locking tutorial</a> (somewhat old)</li>\n<li><a href="http://perldoc.perl.org/functions/flock.html" rel="noreferrer"><code>flock()</code> documentation</a></li>\n</ul>\n\n<p>In response to your added question, I\'d say either place the lock on the file or create a file that you call \'lock\' whenever the file is locked and delete it when it is no longer locked (and then make sure your programs obey those semantics).</p>\n'}, {'answer_id': 38101, 'author': 'Gary Richardson', 'author_id': 2506, 'author_profile': 'https://Stackoverflow.com/users/2506', 'pm_score': 3, 'selected': False, 'text': '<p>CPAN to the rescue: <a href="http://search.cpan.org/~rani/IO-LockedFile-0.23/LockedFile.pm" rel="noreferrer">IO::LockedFile</a>. </p>\n'}, {'answer_id': 79295, 'author': 'Ryan P', 'author_id': 1539, 'author_profile': 'https://Stackoverflow.com/users/1539', 'pm_score': 1, 'selected': False, 'text': '<p>My goal in this question was to lock a file being used as a data store for several scripts. In the end I used similar code to the following (from Chris):</p>\n\n<pre><code>open (FILE, \'&gt;&gt;\', test.dat\') ; # open the file \nflock FILE, 2; # try to lock the file \n# do something with the file here \nclose(FILE); # close the file\n</code></pre>\n\n<p>In his example I removed the flock FILE, 8 as the close(FILE) performs this action as well. The real problem was when the script starts it has to hold the current counter, and when it ends it has to update the counter. This is where Perl has a problem, to read the file you:</p>\n\n<pre><code> open (FILE, \'&lt;\', test.dat\');\n flock FILE, 2;\n</code></pre>\n\n<p>Now I want to write out the results and since i want to overwrite the file I need to reopen and truncate which results in the following:</p>\n\n<pre><code> open (FILE, \'&gt;\', test.dat\'); #single arrow truncates double appends\n flock FILE, 2;\n</code></pre>\n\n<p>In this case the file is actually unlocked for a short period of time while the file is reopened. This demonstrates the case for the external lock file. If you are going to be changing contexts of the file, use a lock file. The modified code:</p>\n\n<pre><code>open (LOCK_FILE, \'&lt;\', test.dat.lock\') or die "Could not obtain lock";\nflock LOCK_FILE, 2;\nopen (FILE, \'&lt;\', test.dat\') or die "Could not open file";\n# read file\n# ...\nopen (FILE, \'&gt;\', test.dat\') or die "Could not reopen file";\n#write file\nclose (FILE);\nclose (LOCK_FILE);\n</code></pre>\n'}, {'answer_id': 79435, 'author': 'Swaroop C H', 'author_id': 4869, 'author_profile': 'https://Stackoverflow.com/users/4869', 'pm_score': 2, 'selected': False, 'text': '<p>Have you considered using the <a href="http://search.cpan.org/perldoc?LockFile::Simple" rel="nofollow noreferrer">LockFile::Simple  module</a>? It does most of the work for you already.</p>\n\n<p>In my past experience, I have found it very easy to use and sturdy.</p>\n'}, {'answer_id': 80825, 'author': 'szabgab', 'author_id': 11827, 'author_profile': 'https://Stackoverflow.com/users/11827', 'pm_score': 3, 'selected': False, 'text': '<p>I think it would be much better to show this with lexical variables as file handlers\nand error handling.\nIt is also better to use the constants from the Fcntl module than hard code the magic number 2 which might not be the right number on all operating systems.</p>\n\n<pre>\n    use Fcntl \':flock\'; # import LOCK_* constants\n\n    # open the file for appending\n    open (my $fh, \'>>\', \'test.dat\') or die $!;\n\n    # try to lock the file exclusively, will wait till you get the lock\n    flock($fh, LOCK_EX);\n\n    # do something with the file here (print to it in our case)\n\n    # actually you should not unlock the file\n    # close the file will unlock it\n    close($fh) or warn "Could not close file $!";\n</pre>\n\n<p>Check out the full <a href="http://perldoc.perl.org/functions/flock.html" rel="nofollow noreferrer">documentation of flock</a> and the <a href="http://www.perlmonks.org/?node_id=7058" rel="nofollow noreferrer">File locking tutorial</a> on PerlMonks even though that also uses the old style of file handle usage.</p>\n\n<p>Actually I usually skip the error handling on close() as there is not\nmuch I can do if it fails anyway.</p>\n\n<p>Regarding what to lock, if you are working in a single file then lock that file. If you need to lock several files at once then - in order to avoid dead locks - it is better to pick one file that you are locking. Does not really matter if that is one of the several files you really need to lock or a separate file you create just for the locking purpose.</p>\n'}, {'answer_id': 81019, 'author': 'Aristotle Pagaltzis', 'author_id': 9410, 'author_profile': 'https://Stackoverflow.com/users/9410', 'pm_score': 3, 'selected': False, 'text': '<p>Ryan P wrote:</p>\n\n<blockquote>\n  <p>In this case the file is actually unlocked for a short period of time while the file is reopened.</p>\n</blockquote>\n\n<p>So don’t do that. Instead, <code>open</code> the file for read/write:</p>\n\n<pre><code>open my $fh, \'+&lt;\', \'test.dat\'\n    or die "Couldn’t open test.dat: $!\\n";\n</code></pre>\n\n<p>When you are ready to write the counter, just <code>seek</code> back to the start of the file. Note that if you do that, you should <code>truncate</code> just before <code>close</code>, so that the file isn’t left with trailing garbage if its new contents are shorter than its previous ones. (Usually, the current position in the file is at its end, so you can just write <code>truncate $fh, tell $fh</code>.)</p>\n\n<p>Also, note that I used three-argument <code>open</code> and a lexical file handle, and I also checked the success of the operation. Please avoid global file handles (global variables are bad, mmkay?) and magic two-argument <code>open</code> (which has been a source of many a(n exploitable) bug in Perl code), and always test whether your <code>open</code>s succeed.</p>\n'}, {'answer_id': 182465, 'author': 'John Siracusa', 'author_id': 164, 'author_profile': 'https://Stackoverflow.com/users/164', 'pm_score': 2, 'selected': False, 'text': '<pre><code>use strict;\n\nuse Fcntl \':flock\'; # Import LOCK_* constants\n\n# We will use this file path in error messages and function calls.\n# Don\'t type it out more than once in your code.  Use a variable.\nmy $file = \'/path/to/some/file\';\n\n# Open the file for appending.  Note the file path is in quoted\n# in the error message.  This helps debug situations where you\n# have a stray space at the start or end of the path.\nopen(my $fh, \'&gt;&gt;\', $file) or die "Could not open \'$file\' - $!";\n\n# Get exclusive lock (will block until it does)\nflock($fh, LOCK_EX);\n\n\n# Do something with the file here...\n\n\n# Do NOT use flock() to unlock the file if you wrote to the\n# file in the "do something" section above.  This could create\n# a race condition.  The close() call below will unlock it\n# for you, but only after writing any buffered data.\n\n# In a world of buffered i/o, some or all of your data will not \n# be written until close() completes.  Always, always, ALWAYS \n# check the return value on close()!\nclose($fh) or die "Could not write \'$file\' - $!";\n</code></pre>\n'}, {'answer_id': 1427007, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 0, 'selected': False, 'text': '<p>Here\'s my solution to reading and writing in one lock...</p>\n\n<pre><code>open (TST,"+&lt; readwrite_test.txt") or die "Cannot open file\\n$!";\nflock(TST, LOCK_EX);\n# Read the file:\n@LINES=&lt;TST&gt;;\n# Wipe the file:\nseek(TST, 0, 0); truncate(TST, 0);\n# Do something with the contents here:\npush @LINES,"grappig, he!\\n";\n$LINES[3]="Gekke henkie!\\n";\n# Write the file:\nforeach $l (@LINES)\n{\n   print TST $l;\n}\nclose(TST) or die "Cannot close file\\n$!";\n</code></pre>\n'}, {'answer_id': 7695560, 'author': 'Alex Dupuy', 'author_id': 18829, 'author_profile': 'https://Stackoverflow.com/users/18829', 'pm_score': 4, 'selected': False, 'text': '<p>The other answers cover Perl flock locking pretty well, but on many Unix/Linux systems there are actually two independent locking systems: BSD flock() and POSIX fcntl()-based locks.</p>\n\n<p>Unless you provide special options to configure when building Perl, its flock will use flock() if available.  This is generally fine and probably what you want if you just need locking within your application (running on a single system).  However, sometimes you need to interact with another application that uses fcntl() locks (like Sendmail, on many systems) or perhaps you need to do file locking across NFS-mounted filesystems.</p>\n\n<p>In those cases, you might want to look at <a href="http://search.cpan.org/~jtt/File-FcntlLock-0.12/lib/File/FcntlLock.pm">File::FcntlLock</a> or <a href="http://search.cpan.org/~phenson/File-Lockf-0.20/lockf.pm">File::lockf</a>.  It is also possible to do fcntl()-based locking in pure Perl (with some hairy and non-portable bits of pack()).</p>\n\n<p>Quick overview of flock/fcntl/lockf differences:</p>\n\n<p>lockf is almost always implemented on top of fcntl, has file-level locking only.  If implemented using fcntl, limitations below also apply to lockf.</p>\n\n<p>fcntl provides range-level locking (within a file) and network locking over NFS, but locks are not inherited by child processes after a fork().  On many systems, you must have the filehandle open read-only to request a shared lock, and read-write to request an exclusive lock.</p>\n\n<p>flock has file-level locking only, locking is only within a single machine (you can lock an NFS-mounted file, but only local processes will see the lock).  Locks are inherited by children (assuming that the file descriptor is not closed).</p>\n\n<p>Sometimes (SYSV systems) flock is emulated using lockf, or fcntl; on some BSD systems lockf is emulated using flock.  Generally these sorts of emulation work poorly and you are well advised to avoid them.</p>\n'}, {'answer_id': 11473761, 'author': 'sean ur', 'author_id': 1523990, 'author_profile': 'https://Stackoverflow.com/users/1523990', 'pm_score': 1, 'selected': False, 'text': '<p>Developed off of <a href="http://metacpan.org/pod/File%3a%3aFcntlLock" rel="nofollow">http://metacpan.org/pod/File::FcntlLock</a></p>\n\n<pre><code>use Fcntl qw(:DEFAULT :flock :seek :Fcompat);\nuse File::FcntlLock;\nsub acquire_lock {\n  my $fn = shift;\n  my $justPrint = shift || 0;\n  confess "Too many args" if defined shift;\n  confess "Not enough args" if !defined $justPrint;\n\n  my $rv = TRUE;\n  my $fh;\n  sysopen($fh, $fn, O_RDWR | O_CREAT) or LOGDIE "failed to open: $fn: $!";\n  $fh-&gt;autoflush(1);\n  ALWAYS "acquiring lock: $fn";\n  my $fs = new File::FcntlLock;\n  $fs-&gt;l_type( F_WRLCK );\n  $fs-&gt;l_whence( SEEK_SET );\n  $fs-&gt;l_start( 0 );\n  $fs-&gt;lock( $fh, F_SETLKW ) or LOGDIE  "failed to get write lock: $fn:" . $fs-&gt;error;\n  my $num = &lt;$fh&gt; || 0;\n  return ($fh, $num);\n}\n\nsub release_lock {\n  my $fn = shift;\n  my $fh = shift;\n  my $num = shift;\n  my $justPrint = shift || 0;\n\n  seek($fh, 0, SEEK_SET) or LOGDIE "seek failed: $fn: $!";\n  print $fh "$num\\n" or LOGDIE "write failed: $fn: $!";\n  truncate($fh, tell($fh)) or LOGDIE "truncate failed: $fn: $!";\n  my $fs = new File::FcntlLock;\n  $fs-&gt;l_type(F_UNLCK);\n  ALWAYS "releasing lock: $fn";\n  $fs-&gt;lock( $fh, F_SETLK ) or LOGDIE "unlock failed: $fn: " . $fs-&gt;error;\n  close($fh) or LOGDIE "close failed: $fn: $!";\n}\n</code></pre>\n'}, {'answer_id': 25940666, 'author': 'Mark Lawrence', 'author_id': 1450404, 'author_profile': 'https://Stackoverflow.com/users/1450404', 'pm_score': 1, 'selected': False, 'text': '<p>One alternative to the lock <em>file</em> approach is to use a lock <em>socket</em>. See <a href="http://metacpan.org/pod/Lock::Socket" rel="nofollow">Lock::Socket</a> on CPAN for such an implementation. Usage is as simple as the following:</p>\n\n<pre><code>use Lock::Socket qw/lock_socket/;\nmy $lock = lock_socket(5197); # raises exception if lock already taken\n</code></pre>\n\n<p>There are a couple of advantages to using a socket:</p>\n\n<ul>\n<li>guaranteed (through the operating system) that no two applications will hold the same lock: there is no race condition.</li>\n<li>guaranteed (again through the operating system) to clean up neatly when your process exits, so there are no stale locks to deal with.</li>\n<li>relies on functionality that is well supported by anything that Perl runs on: no issues with flock(2) support on Win32 for example.</li>\n</ul>\n\n<p>The obvious disadvantage is of course that the lock namespace is global. It is possible for a kind of denial-of-service if another process decides to lock the port you need.</p>\n\n<p>[disclosure: I am the author of the afor-mentioned module]</p>\n'}, {'answer_id': 60920788, 'author': 'Ben White', 'author_id': 7141376, 'author_profile': 'https://Stackoverflow.com/users/7141376', 'pm_score': 0, 'selected': False, 'text': "<p>Flock is probably the best but requires you to write all the supporting code around it - timeouts, stale locks, non-existant files etc.\nI trued LockFile::Simple but found it started setting the default umask to readonly and not cleaning this up. Resulting in random permissions problems on a multi process/multi-threaded application on modperl\nI've settled on wrapping up NFSLock with some empty file handling.</p>\n"}]
['https://Stackoverflow.com/questions/34920', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/1539/']