Na documentação do Open Group , afirma-se que:
NAME
pthread_rwlock_wrlock, pthread_rwlock_trywrlock - lock a read-write lock object for writing
...
The pthread_rwlock_wrlock() and pthread_rwlock_trywrlock() functions may fail if:
...
[EDEADLK]
The current thread already owns the read-write lock for writing or reading.
Entretanto, quando executo o seguinte código:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
int main()
{
int error;
pthread_rwlock_t *mutex = (pthread_rwlock_t *)malloc(sizeof(pthread_rwlock_t));
if (mutex == NULL) {
perror("malloc");
abort();
}
pthread_rwlockattr_t attr;
error = pthread_rwlockattr_init(&attr);
if (error != 0)
{
fprintf(stderr, "%s:%d: pthread_rwlockattr_init failed: %s", __FILE__, __LINE__, strerror(error));
abort();
}
error = pthread_rwlock_init(mutex, &attr);
if (error != 0)
{
fprintf(stderr, "%s:%d: pthread_rwlock_init failed: %s", __FILE__, __LINE__, strerror(error));
abort();
}
error = pthread_rwlock_wrlock(mutex);
if (error != 0)
{
fprintf(stderr, "%s:%d: pthread_rwlock_wrlock failed: %s", __FILE__, __LINE__, strerror(error));
abort();
}
error = pthread_rwlock_rdlock(mutex);
if (error != 0)
{
fprintf(stderr, "%s:%d: pthread_rwlock_rdlock failed: %s", __FILE__, __LINE__, strerror(error));
abort();
}
return 0;
}
A saída é:
main.c:53: pthread_rwlock_rdlock failed: Resource deadlock avoided
Mas quando executo o seguinte código:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
int main()
{
int error;
pthread_rwlock_t *mutex = (pthread_rwlock_t *)malloc(sizeof(pthread_rwlock_t));
if (mutex == NULL) {
perror("malloc");
abort();
}
pthread_rwlockattr_t attr;
error = pthread_rwlockattr_init(&attr);
if (error != 0)
{
fprintf(stderr, "%s:%d: pthread_rwlockattr_init failed: %s", __FILE__, __LINE__, strerror(error));
abort();
}
error = pthread_rwlock_init(mutex, &attr);
if (error != 0)
{
fprintf(stderr, "%s:%d: pthread_rwlock_init failed: %s", __FILE__, __LINE__, strerror(error));
abort();
}
error = pthread_rwlock_rdlock(mutex);
if (error != 0)
{
fprintf(stderr, "%s:%d: pthread_rwlock_rdlock failed: %s", __FILE__, __LINE__, strerror(error));
abort();
}
error = pthread_rwlock_wrlock(mutex);
if (error != 0)
{
fprintf(stderr, "%s:%d: pthread_rwlock_wrlock failed: %s", __FILE__, __LINE__, strerror(error));
abort();
}
return 0;
}
Nesse caso, a pthread_rwlock_wrlock
chamada não retorna EDEADLK
e é bloqueada.
A explicação do Open Group está incorreta? Parece mais razoável que EDEADLK
seja devolvida. Qual poderia ser o problema aqui?
Testei isso no Linux usando o gcc, no meu computador com o WSL e também no OnlineGDB, e não funciona em nenhum desses ambientes. Parece ser um problema comum de implementação, e não um problema específico da minha configuração. Esse comportamento é intencional?
Você foi seletivo demais na parte do documento que citou. A "Descrição" está entre as seções normativas e inclui o seguinte:
(Ênfase adicionada)
Isso é um tanto inconsistente com a parte que você citou. Uma reconciliação razoável que dá um significado não trivial a ambas as partes seria que a implementação tem permissão para manifestar qualquer comportamento, mas que entre suas alternativas está explicitamente retornar o código de erro
EDEADLK
, e que esse é o significado desse código de erro se uma implementação o retornar.Dito isso, a documentação para a qual você se referiu está obsoleta. Houve pelo menos três revisões subsequentes do POSIX.1. A versão mais recente do POSIX resolve a inconsistência com uma versão diferente do texto citado acima:
... e mudando
EDEADLK
de "deve falhar" para "pode falhar".Observe que, embora a implementação agora ofereça alternativas, o comportamento não é mais indefinido e nenhuma parte da documentação promete mais
EDEADLK
. Isso é consistente com o comportamento que você observa no seu teste.A afirmação explícita de que uma implementação pode entrar em deadlock sob as circunstâncias que você descreve remonta à edição de 2004 do POSIX.1 , embora a linguagem ali seja um pouco diferente de ambas as anteriores.