dadv: (chuck)
[personal profile] dadv

perl-threaded-5.14.4 (собран с useithreads=define, usemultiplicity=define).

Код такого вида:

#!/usr/bin/perl

use threads;
use threads::shared;
use strict;
use warnings;

our $db :shared;

sub func() {
  my $new;
  ... # формируем новые данные
  {   # пытаемся обновить $db, удерживая блокировку
    lock($db);
    $db = $new;
    $new = undef;
  }
}

Такой код проходит все проверки синтаксиса, но во время работы нить, выполняющая func() второй раз, аварийно завершает работу на строке $db = $new lock($db) с диагностикой panic: MUTEX_LOCK (22) [shared.xs:200].

Ошибка 22 это EINVAL. В потрохах perl есть dist/threads-shared/shared.xs и в нём функция recursive_lock_release(pTHX_ recursive_lock_t *lock), которая зовёт MUTEX_LOCK(&lock->mutex) - макрос, который выкидывает этот panic, если неуспешно завершается системная функция pthread_mutex_lock() из POSIX Threads Library (libpthread, -lpthread). А она возвращает EINVAL, если переданный мутекс равен THR_MUTEX_DESTROYED.

Выходит, переписывание скаляра новым значением при удерживании блокировки разрушает мутекс. Решение было очевидным: завести под блокировку отдельный скаляр $dblock и при разграничении доступа к $db лочить $dblock.

Update: test-case.

Date: 2013-11-15 09:20 (UTC)
From: [identity profile] dadv.livejournal.com
Это почти "псевдокод", в нём для реального воспроизведения баги кучи всего не хватает.

Date: 2013-11-15 12:21 (UTC)
From: [identity profile] http://users.livejournal.com/_slw/
так напиши что бы хватало

Date: 2013-11-16 00:14 (UTC)
From: [identity profile] dadv.livejournal.com
http://www.grosbein.net/files/panic.pl

Выдаёт:

func: new iteration started
func: iteration finished
func: new iteration started
Thread 1 terminated abnormally: panic: MUTEX_LOCK (22) [shared.xs:200] at ./panic.pl line 21.

Date: 2013-11-16 00:34 (UTC)
From: [identity profile] dadv.livejournal.com
Если даже $new сделать разделяемой, ничего не меняется.

--- panic.pl    2013-11-16 07:11:49.000000000 +0700
+++ panic2.pl   2013-11-16 07:31:53.000000000 +0700
@@ -8,9 +8,9 @@
 $|=1;
 
 our $db :shared;
+our $new :shared;
 
 sub func() {
-  my $new;
 
   while (1) {
     print STDERR "func: new iteration started\n";

Profile

dadv: (Default)
Choose your future

July 2024

M T W T F S S
12 34567
891011121314
15161718192021
22232425262728
293031    

Tags

Style Credit

Powered by Dreamwidth Studios