perl & panic: MUTEX_LOCK
2013-11-15 14:31perl-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.