Ahmed_Faraz
Ahmed_Faraz

Reputation: 635

pthread wrlock method blocks if unlock is called before wrlock

I am using Ubuntu 20.04 and faced a strange problem. In my code, if by any chance after initializing the pthread_rwlock_t object the pthread_rwlock_unlock function is called before pthread_rwlock_wrlock in the same thread, the execution blocks. Here is a sample code to reproduce the problem

#include <stdio.h> 
#include <pthread.h> 
pthread_rwlock_t rwlock;
int main() {

    pthread_rwlock_init(&rwlock, NULL);

    pthread_rwlock_unlock(&rwlock);
    pthread_rwlock_wrlock(&rwlock);  //Blocks indefinitely 
}

But it doesn't happen once wrlock is called and then unlocked is called. e.g

#include <stdio.h> 
#include <pthread.h> 
pthread_rwlock_t rwlock;
int main() {

    pthread_rwlock_init(&rwlock, NULL);
    pthread_rwlock_wrlock(&rwlock);
    pthread_rwlock_unlock(&rwlock);
    pthread_rwlock_unlock(&rwlock);
    pthread_rwlock_wrlock(&rwlock);  //Doesn't Block even though unlock is called twice
}

Upvotes: 0

Views: 312

Answers (1)

Sam Varshavchik
Sam Varshavchik

Reputation: 118445

pthread_rwlock_init(&rwlock, NULL);

This initializes a new pthread_rwlock_t structure. The initial state is that it's unlocked. Nothing locked yet it.

pthread_rwlock_unlock(&rwlock);

This unlocks the pthread_rwlock_t structure. However it is not locked, as we've determined already. This is undefined behavior.

But it doesn't happen once wrlock is called and then unlocked is called. e.g

This is irrelevant. Undefined behavior is undefined behavior. You have no expectations, whatsoever, of the consequences of undefined behavior. The actual reasons for the observed behavior, and why they differ in mostly similar situations, is immaterial. You might wake up tomorrow and discover that tomorrow both instances produce the same results. That can happen. That's what undefined behavior means. It is undefined. You cannot wrap your arms around it, or expect to get the same results every time.

The actual reason obviously has to do with the internal implementation of these locking primitives. But that's still irrelevant. The day after tomorrow you might update your kernel or C library, and the actual results of undefined behavior will become different again, because this internal logic was updated for some reason. You can't rely on it. So, the practical results of undefined behavior have no value or merit in them.

Upvotes: 4

Related Questions