我正在尝试测试一段代码($code),它应该确保一次只运行一个程序实例:
#!/usr/bin/perl
# test_lock
use strict;
use warnings;
( my $code = <<'CODE') =~ s/^\s+//gm;
#!/usr/bin/perl
use strict;
use warnings;
use Fcntl qw(:flock);
# Make sure only one instance of the program is running at a time.
open our $Lock, '<', $0 or die "Can't lock myself $0: $!";
flock $Lock, LOCK_EX | LOCK_NB
or die "Another instance of $0 is already running. Exiting ...\n";
sleep(2);
CODE
my $progfile = '/tmp/x';
open my $fh, '>', $progfile or die $!;
print $fh $code;
close $fh;
$|++;
my $ex1 = system("perl $progfile &");
print "First system(): $ex1\n";
my $ex2 = system("perl $progfile");
print "Second system(): $ex2\n";
Run Code Online (Sandbox Code Playgroud)
我期望第二次调用system()将返回非零值($ex2),因为它无法获得锁定和dies.但是我得到:
$ perl test_lock
First system(): 0
Another instance of /tmp/x is already running. Exiting ...
Second system(): 0
Run Code Online (Sandbox Code Playgroud)
我的假设有什么问题?(有没有更好的方法来测试$code?)
我想这可能是因为你有竞争条件.你怎么知道这个错误实际上来自你的第二个过程?
因为,例如,运行:
perl /tmp/x & perl /tmp/x ; echo $?
Run Code Online (Sandbox Code Playgroud)
您可能获得零回报,因为竞赛的"赢家"可能是后一个过程(返回您正在捕获的代码).(尝试几次,你会看到不同的结果)
你也确实有两个命令在shell之间做了一些细微的差别 - 来自docs:
如果只有一个标量参数,该参数检查shell元字符,如果有的话,整个参数传递到系统的命令shell解析(这是/ bin/sh的Unix平台-c,但变化上其他平台).如果参数中没有shell元字符,则将其拆分为单词并直接传递给execvp,这样效率更高.
所以实际上你应该在你的第一个中看到sh之前的调用perl,这意味着它实际上更有可能需要更长的时间才能到达锁定点.
这意味着你的命令更像是:
sh -c "perl /tmp/x"& perl /tmp/x; echo $?
Run Code Online (Sandbox Code Playgroud)
运行几次,看看你获得非零错误代码的次数.这通常并不常见,因为通常shell启动的"延迟"足以确保第二个实例在大多数时间赢得比赛!
如果你有linux - 尝试strace -fTt yourscript哪个将跟踪执行流程.或者您可以$$在运行时明智地使用报告进程pid.
| 归档时间: |
|
| 查看次数: |
162 次 |
| 最近记录: |