Thorium

 view release on metacpan or  search on metacpan

lib/Thorium/Utils.pm  view on Meta::CPAN

  $Thorium::Utils::VERSION = '0.510';
}
BEGIN {
  $Thorium::Utils::AUTHORITY = 'cpan:AFLOTT';
}

# ABSTRACT: additional utilities

use Thorium::Protection;

# core
use Fcntl ':flock';
use FindBin qw();
use Time::HiRes qw();

# CPAN
use File::Slurp qw(read_file);
use IPC::Cmd qw();
use Params::Util qw();
use Proc::ProcessTable;
use Sub::Exporter;

my @funcs_names = qw(block_new_invocations unblock_new_invocations page execute already_running halt run);

Sub::Exporter::setup_exporter(
    {
        'exports' => \@funcs_names,
        'groups'  => {'default' => \@funcs_names}
    }
);

our $Lock_FH;
our $Lock_Filename;

my %old_sig_int_handlers;

for my $sig_name (qw(INT TERM)) {
    if ($SIG{$sig_name} && defined(&{$SIG{$sig_name}})) {
        $old_sig_int_handlers{$sig_name} = $SIG{$sig_name};
    }
}

# Allows the END {} block below to be called
sub _sig_handler {
    my ($sig_name) = @_;

    if ($old_sig_int_handlers{$sig_name}) {
        $old_sig_int_handlers{$sig_name}->(@_);
    }

    die("Caught $sig_name, aborting\n");
}

local $SIG{'INT'}  = \&_sig_handler;
local $SIG{'TERM'} = \&_sig_handler;

sub block_new_invocations {
    my ($lock_file) = @_;

    unless ($lock_file) {
        my $username = getlogin || getpwuid($<) || 'unknown';
        my $s = $FindBin::Script;

        # clean up the filename so it's easier to read and Unix-safe
        $s =~ s/[.\-]/_/g;
        $s =~ s/[\{\[\(\<>)\]\}~\|\/]/_/g;
        $s =~ s/[\p{Zs}\t]+/_/g;
        $s =~ s/\&+/_and_/g;
        $s =~ s/[^\p{Alphabetic}\p{Nd}\-\.\+_]//g;

        $lock_file = sprintf('/tmp/thorium_utils_lock_file_%s_%s.lock', $username, $s);
    }

    if (-e $lock_file) {
        die("The lock file, $lock_file, already exists, most likely this process ($FindBin::Script) is already running. If not, delete the file and run again.\n");
    }

    if ($Lock_FH && Params::Utils::_HANDLE($Lock_FH)) {
        warn('The global file handle has already been initialized. Call Thorium::Utils::unblock_new_invocations() to release lock.');
        return;
    }

    open($Lock_FH, '>', $lock_file) or die("Could not create/open lock file '$lock_file' - $!\n");

    unless (flock($Lock_FH, LOCK_EX | LOCK_NB)) {
        $Lock_FH = undef;

        die("flock() failed - $!\n");
    }

    $Lock_Filename = $lock_file;

    return $Lock_FH;
}

sub unblock_new_invocations {
    if ($Lock_FH) {
        flock($Lock_FH, LOCK_UN);
        close($Lock_FH);
        unlink($Lock_Filename);
    }

    return;
}

sub already_running {
    my $filename   = Params::Util::_STRING(shift(@_)) or die("Please pass the full file path to the pid file as the first argument to already_running()\n");
    my $executable = Params::Util::_STRING(shift(@_)) or die("Please pass the full executable file path as the second argument to already_running()\n");

    if (-e -r -s $filename) {
        my $pt = Proc::ProcessTable->new;

        my $pid = read_file($filename);

        foreach my $p (@{$pt->table}) {
            if ($p->pid == $pid && $p->cmndline =~ $executable) {
                return 1;
            }
        }
    }



( run in 1.506 second using v1.01-cache-2.11-cpan-39bf76dae61 )