Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Release of flock in case of errors?

Imagine the following Perl code (here in pseudo code):

successfully acquired flock for FILEHANDLER       # line 1
some error or maybe simply a call to exit()       # line 2
close FILEHANDLER (which also releases the lock)  # line 3

In this case I wouldn't release the lock, as the Perl script ends in line 2. In that case, is the lock ever released by the operating system? Does it see "hey, the script that acquired the lock crashed" and release the lock? Does it release the lock immediately? Also, is there one Perl instance running for each script, so that it's clear which script crashed/stopped without releasing the lock?

like image 820
stefan.at.wpf Avatar asked Sep 29 '12 08:09

stefan.at.wpf


People also ask

How does flock work?

The process uses special equipment that electrically charges the flock particles causing them to stand-up. The fibres are then propelled and anchored into the adhesive at right angles to the substrate. The application is both durable and permanent. Flock can be applied to glass, metal, plastic, paper or textiles.

What is flock system call?

A call to flock() may block if an incompatible lock is held by another process. To make a nonblocking request, include LOCK_NB (by ORing) with any of the above operations. A single file may not simultaneously have both shared and exclusive locks.

What does flock do in Linux?

The flock command is also provided by the util-linux package. This utility allows us to manage advisory file locks in shell scripts or on the command line.

What is flock PHP?

flock() function in PHP The flock() function locks or releases a file. The function returns TRUE on success and FALSE on failure.


2 Answers

In that case, is the lock ever released by the operating system?
Does it see "hey, the script that acquired the lock crashed" and release the lock?
Does it release the lock immediately?

All of these questions are system dependent. Perl 5 does not implement a file locking function, it just provides a common interface to flock(2), fcntl(2) locking, or lockf(3) (depending on what is available in the OS). There may also be a difference between what happens when a program exits, segfaults, or is killed with a sigkill.

A quick test under Linux shows that a lock is removed under normal exit conditions:

$ perl -le 'open my $fh, ">", "f" or die $!; print flock($fh, 6) ? "got lock" : "was already locked", "\n"'
got lock
$ perl -le 'open my $fh, ">", "f" or die $!; print flock($fh, 6) ? "got lock" : "was already locked", "\n"'
got lock

Let's see what happens when we die:

$ perl -le 'open my $fh, ">", "f" or die $!; print flock($fh, 6) ? "got lock" : "was already locked", "\n"; die "died"'
got lock
died at -e line 1.
$ perl -le 'open my $fh, ">", "f" or die $!; print flock($fh, 6) ? "got lock" : "was already locked", "\n"; die "died"'
got lock
died at -e line 1.

To get a segfault, we will need access to C, I am using Inline to get it:

$ cat segfault.pl
#!/usr/bin/perl

use strict;
use warnings;

use Inline "C";

open my $fh, ">", "f" or die $!;

print flock($fh, 6) ? "got lock" : "was already locked", "\n";

crash();

__DATA__
__C__

void crash() {
    int* ptr = NULL;
    *ptr = 5;
}
$ perl segfault.pl
got lock
Segmentation fault
$ perl segfault.pl
got lock
Segmentation fault

And finally, here is what happens when a program is sent SIGKILL:

$ cat fork.pl
#!/usr/bin/perl

use strict;
use warnings;

$SIG{CHLD} = "IGNORE"; #auto-reap children

die "could not fork: $!" unless defined(my $pid = fork);
unless ($pid) {
    #child
    open my $fh, ">", "f" or die $!;
    print flock($fh, 6) ? "got lock" : "was already locked", "\n";
    sleep(100);
    exit;
}

kill 9, $pid;

die "could not fork: $!" unless defined($pid = fork);
unless ($pid) {
    #child
    open my $fh, ">", "f" or die $!;
    print flock($fh, 6) ? "got lock" : "was already locked", "\n";
    exit;
}
$ perl fork.pl
got lock
got lock

From these experiments, we can see that the lock is released in Linux for each of the cases you were concerned with.

Also, is there one perl instance running for each script, so that it's clear which script crashed/stopped without releasing the lock?

Yes, Perl 5 has one perl process per script. Even if you fork, the child gets its own perl process. Threading does not provide a separate perl process.

Note: if a parent process gets a lock and does not give it up before locking, then the child will have the same lock even if the parent exits.

like image 92
Chas. Owens Avatar answered Oct 25 '22 19:10

Chas. Owens


When the program exits, the OS automatically releases all locks acquired by the program and closes all files opened by the program.

like image 29
snoofkin Avatar answered Oct 25 '22 19:10

snoofkin