mirror of
git://git.proxmox.com/git/pve-common.git
synced 2024-12-22 21:33:47 +03:00
903d285751
There are differences for error handling in the old and new helper, in particular when the child is signaled. But the test here does not explicitly check for specific error conditions or messages and is therefore still correct with the new helper. Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
126 lines
2.6 KiB
Perl
Executable File
126 lines
2.6 KiB
Perl
Executable File
#!/usr/bin/perl
|
|
|
|
use lib '../src';
|
|
use strict;
|
|
use warnings;
|
|
|
|
use Socket;
|
|
use POSIX (); # don't import assert()
|
|
|
|
use PVE::Tools 'lock_file_full';
|
|
|
|
my $name = "test.lockfile.$$-";
|
|
|
|
# Book-keeping:
|
|
|
|
my %_ran;
|
|
sub new {
|
|
%_ran = ();
|
|
}
|
|
sub ran {
|
|
my ($what) = @_;
|
|
$_ran{$what} = 1;
|
|
}
|
|
sub assert {
|
|
my ($what) = @_;
|
|
die "code didn't run: $what\n" if !$_ran{$what};
|
|
}
|
|
sub assert_not {
|
|
my ($what) = @_;
|
|
die "code shouldn't have run: $what\n" if $_ran{$what};
|
|
}
|
|
|
|
# Does it actually lock? (shared=0)
|
|
# Can we get two simultaneous shared locks? (shared=1)
|
|
sub forktest1($) {
|
|
my ($shared) = @_;
|
|
new();
|
|
# socket pair for synchronization
|
|
socketpair(my $fmain, my $fother, AF_UNIX, SOCK_STREAM, PF_UNSPEC)
|
|
or die "socketpair(): $!\n";
|
|
my $other = sub {
|
|
# other side
|
|
close($fmain);
|
|
my $line;
|
|
lock_file_full($name, 60, $shared, sub {
|
|
ran('other side');
|
|
# tell parent we've acquired the lock
|
|
print {$fother} "1\n";
|
|
$fother->flush();
|
|
# wait for parent to be done trying to lock
|
|
$line = <$fother>;
|
|
});
|
|
die $@ if $@;
|
|
die "parent failed\n" if !$line || $line ne "2\n";
|
|
assert('other side');
|
|
return;
|
|
};
|
|
my $main = sub {
|
|
# main process
|
|
# Wait for our child to lock:
|
|
close($fother);
|
|
my $line = <$fmain>;
|
|
die "child failed to acquire a lock\n" if !$line || $line ne "1\n";
|
|
lock_file_full($name, 1, $shared, sub {
|
|
ran('local side');
|
|
});
|
|
if ($shared) {
|
|
assert('local side');
|
|
} else {
|
|
assert_not('local side');
|
|
}
|
|
print {$fmain} "2\n";
|
|
$fmain->flush();
|
|
};
|
|
|
|
PVE::Tools::run_fork($other, { afterfork => $main });
|
|
close($fmain);
|
|
}
|
|
|
|
eval {
|
|
# Regular lock:
|
|
new();
|
|
lock_file_full($name, 10, 0, sub { ran('single lock') });
|
|
assert('single lock');
|
|
|
|
# Lock multiple times in a row:
|
|
new();
|
|
lock_file_full($name, 10, 0, sub { ran('lock A') });
|
|
assert('lock A');
|
|
lock_file_full($name, 10, 0, sub { ran('lock B') });
|
|
assert('lock B');
|
|
|
|
# Nested lock:
|
|
new();
|
|
lock_file_full($name, 10, 0, sub {
|
|
ran('lock A');
|
|
lock_file_full($name, 10, 0, sub { ran('lock B') });
|
|
assert('lock B');
|
|
ran('lock C');
|
|
});
|
|
assert('lock A');
|
|
assert('lock B');
|
|
assert('lock C');
|
|
|
|
# Independent locks:
|
|
new();
|
|
lock_file_full($name, 10, 0, sub {
|
|
ran('lock A');
|
|
# locks file "${name}2"
|
|
lock_file_full($name.2, 10, 0, sub { ran('lock B') });
|
|
assert('lock B');
|
|
ran('lock C');
|
|
});
|
|
assert('lock A');
|
|
assert('lock B');
|
|
assert('lock C');
|
|
|
|
# Does it actually lock? (shared=0)
|
|
# Can we get two simultaneous shared locks? (shared=1)
|
|
forktest1(0);
|
|
forktest1(1);
|
|
};
|
|
my $err = $@;
|
|
system("rm $name*");
|
|
die $err if $err;
|