dadv: (chuck)

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.

Profile

dadv: (Default)
Choose your future

June 2017

M T W T F S S
   1234
56 7891011
12131415161718
19202122232425
2627282930  

Syndicate

RSS Atom

Tags

Style Credit

Powered by Dreamwidth Studios