#!/usr/bin/perl use threads; use strict; use warnings; use DBI; use Time::HiRes qw(sleep); my ($dbname, $dbuser, $dbpass) = ("OOM", "", ""); my $threadsCount = 20; my $secureWithNamedLock = 0; my %threadInfos; $SIG{TERM} = sub { warn "Terminating...\n"; foreach my $thread (map { $_->{thread} } values %threadInfos) { $thread->kill('TERM')->join(); } warn "All threads are killed. Exiting.\n"; }; # start the threads foreach my $i (1..$threadsCount) { my $thread = threads->create( sub { local $SIG{TERM} = sub { warn sprintf("thread received term signal\n"); die "stopped\n"; }; eval { my $dbh = DBI->connect( sprintf("DBI:mysql:host=%s;database=%s", "localhost", $dbname), $dbuser, $dbpass, { RaiseError => 1, }, ) or die sprintf("Cannot connect to database (%s).\n", $dbname); my @modes = qw(WRITE); my @tables = qw(table_to_update with_trigger2); my @tables2 = qw(with_trigger2 with_trigger3); foreach (1..10) { my $table = getRandomValue(@tables); my $mode = getRandomValue(@modes); my $lockSQL = "LOCK TABLES $table $mode"; printf("Locking tables: %s\n", $lockSQL); $dbh->do("SELECT GET_LOCK('OOM_FIX', -1)") if $secureWithNamedLock; $dbh->do($lockSQL); sleep 0.1; printf("Unlocking tables\n"); $dbh->do("UNLOCK TABLES"); $dbh->do("SELECT RELEASE_LOCK('OOM_FIX')") if $secureWithNamedLock; } }; my $error = $@; if ($error) { die $error unless $error ne "stopped\n"; } }); $threadInfos{$i} = { thread => $thread, }; } my $runningThreads; do { print "Checking threads...\n"; $runningThreads = 0; foreach my $threadInfo (values %threadInfos) { my $thread = $threadInfo->{'thread'}; next unless $thread; if ($thread->is_running()) { $runningThreads++; } elsif ($thread->is_joinable()) { printf("joining finished thread with id: %s\n", $thread->tid); $thread->join; } } sleep 1; } while ($runningThreads > 0); exit 0; sub getRandomValue { return $_[int(rand(scalar(@_)))]; }