Subject: | Race condition in ttydevsfile cache creation |
The following perl script is likely to exhibit a race condition:
#!/usr/bin/perl -w
use strict;
use Proc::ProcessTable;
unlink $Proc::ProcessTable::TTYDEVSFILE;
if (fork == 0) {
my $p = Proc::ProcessTable->new(cache_ttys => 1);
warn "ok $$";
} else {
my $p = Proc::ProcessTable->new(cache_ttys => 1);
warn "ok $$";
}
__END__
Running this script often shows output like this:
$ perl proc-processtable-race-min.pl
/tmp/TTYDEVS_12345678 was created by other process at /opt/perl-5.20.1/lib/site_perl/5.20.1/x86_64-linux/Proc/ProcessTable.pm line 117.
ok 11416 at /tmp/proc-processtable-race-min.pl line 9.
... which means that one of the two processes died.
There's another possible race that is more difficult to exploit: the 2nd process could start reading an unfinished Storable file. This would show up as the following error:
Magic number checking on storable file failed at /usr/perl5.22.1sp/lib/5.22.1/amd64-freebsd/Storable.pm line 383, at proc-proctable-race.pl line 26.
(To see this problem, one has to put some sleep() statements in the code).
A suggestion to fix these races: if the cache file does not exist, then write first to a temporary file (no O_EXCL etc. needed here) and then do a atomic rename. If this rename fails because another process was faster, then don't die. I can create a pull request if you agree on this change.