mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 20:12:31 +01:00
2943d2b7e9
perl The problem here was the method how MTR gets its unique thread ids. Prior to this patch, the method to do it was to maintain a global table of pid,mtr_unique_id) pairs. The table was backed by a text file. The table was cleaned up one in a while and dead processes leaking unique_ids were determined with with kill(0) or with scripting tasklist on Windows. This method is flawed specifically on native Windows Perl. fork() is implemented with starting a new thread, give it a syntetic negative PID (threadID*(-1)), until this thread creates a new process with exec() However, neither tasklist nor any other native Windows tool can cope with negative perl PIDs. This lead to incorrect determination of dead process and reusing already used mtr_unique_id. The patch introduces alternative portable method of solving unique-id problem. When a process needs a unique id in range [min...max], it just starts to open files named min, min+1,...max in a loop . After file is opened, we do non-blocking flock(). When flock() succeeds, process has allocated the ID. When process dies, file is unlocked . Checks for zombies are not necessary. Since the change would create a co-existence problems with older version of MTR, because of different way to calculate IDs, the default ID range is changed from 250-299 to 300-349. Another fix that was necessary enable --parallel option was to serialize spawn() calls on Windows. specifically, IO redirects needed to be protected. This patch also fixes hanging CRTL-C (as described in Bug #38629) for the "new" MTR. The fix was already in 6.0 and is now downported.
129 lines
2.6 KiB
Perl
129 lines
2.6 KiB
Perl
# -*- cperl -*-
|
|
# Copyright (C) 2006 MySQL AB
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; version 2 of the License.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
package mtr_unique;
|
|
|
|
use strict;
|
|
use Fcntl ':flock';
|
|
|
|
use base qw(Exporter);
|
|
our @EXPORT= qw(mtr_get_unique_id mtr_release_unique_id);
|
|
|
|
use My::Platform;
|
|
|
|
sub msg {
|
|
# print "### unique($$) - ", join(" ", @_), "\n";
|
|
}
|
|
|
|
my $dir;
|
|
|
|
if(!IS_WINDOWS)
|
|
{
|
|
$dir= "/tmp/mysql-unique-ids";
|
|
}
|
|
else
|
|
{
|
|
# Try to use machine-wide directory location for unique IDs,
|
|
# $ALLUSERSPROFILE . IF it is not available, fallback to $TEMP
|
|
# which is typically a per-user temporary directory
|
|
if (exists $ENV{'ALLUSERSPROFILE'} && -w $ENV{'ALLUSERSPROFILE'})
|
|
{
|
|
$dir= $ENV{'ALLUSERSPROFILE'}."/mysql-unique-ids";
|
|
}
|
|
else
|
|
{
|
|
$dir= $ENV{'TEMP'}."/mysql-unique-ids";
|
|
}
|
|
}
|
|
|
|
my $mtr_unique_fh = undef;
|
|
|
|
END
|
|
{
|
|
mtr_release_unique_id();
|
|
}
|
|
|
|
#
|
|
# Get a unique, numerical ID in a specified range.
|
|
#
|
|
# If no unique ID within the specified parameters can be
|
|
# obtained, return undef.
|
|
#
|
|
sub mtr_get_unique_id($$) {
|
|
my ($min, $max)= @_;;
|
|
|
|
msg("get $min-$max, $$");
|
|
|
|
die "Can only get one unique id per process!" if defined $mtr_unique_fh;
|
|
|
|
|
|
# Make sure our ID directory exists
|
|
if (! -d $dir)
|
|
{
|
|
# If there is a file with the reserved
|
|
# directory name, just delete the file.
|
|
if (-e $dir)
|
|
{
|
|
unlink($dir);
|
|
}
|
|
|
|
mkdir $dir;
|
|
chmod 0777, $dir;
|
|
|
|
if(! -d $dir)
|
|
{
|
|
die "can't make directory $dir";
|
|
}
|
|
}
|
|
|
|
|
|
my $fh;
|
|
for(my $id = $min; $id <= $max; $id++)
|
|
{
|
|
open( $fh, ">$dir/$id");
|
|
chmod 0666, "$dir/$id";
|
|
# Try to lock the file exclusively. If lock succeeds, we're done.
|
|
if (flock($fh, LOCK_EX|LOCK_NB))
|
|
{
|
|
# Store file handle - we would need it to release the ID (==unlock the file)
|
|
$mtr_unique_fh = $fh;
|
|
return $id;
|
|
}
|
|
else
|
|
{
|
|
close $fh;
|
|
}
|
|
}
|
|
return undef;
|
|
}
|
|
|
|
|
|
#
|
|
# Release a unique ID.
|
|
#
|
|
sub mtr_release_unique_id()
|
|
{
|
|
msg("release $$");
|
|
if (defined $mtr_unique_fh)
|
|
{
|
|
close $mtr_unique_fh;
|
|
$mtr_unique_fh = undef;
|
|
}
|
|
}
|
|
|
|
|
|
1;
|
|
|