/* gcc -lpthread -lc -o robust-mutex-timedout-hangs robust-mutex-timedout-hangs.c */ /* robust-mutex-timedout-hangs.c */ #include #include #include #include #include #include #define PRT(fmt, arg...) printf("[%d] (%d) "fmt"\n", syscall(SYS_gettid), __LINE__, ##arg) pthread_mutex_t mutex; pthread_mutex_t pp = PTHREAD_MUTEX_INITIALIZER; void *child(void *arg) { int ret; PRT("Start Child..."); PRT("Lock Mutex"); ret = pthread_mutex_lock(&mutex); if (ret == 0) PRT("Acquire Mutex"); else PRT("ERR : %d", ret); sleep(1); do { PRT("Trylock..."); ret = pthread_mutex_trylock(&pp); if (ret == 0) { PRT("Trylock... Lock!!!"); break; } sleep(1); } while(1); PRT("Unlock pp Mutex"); ret = pthread_mutex_unlock(&pp); if (ret != 0) PRT("ERR : %d", ret); PRT("End Child"); } void *parent(void *arg) { int ret; struct timespec abstime; PRT("Start Parent..."); PRT("Lock pp Mutex"); ret = pthread_mutex_lock(&pp); if (ret == 0) PRT("Acquire pp Mutex"); else PRT("ERR : %d", ret); sleep(1); do { clock_gettime(CLOCK_REALTIME, &abstime); abstime.tv_sec += 5; PRT("Timedlock..."); ret = pthread_mutex_timedlock(&mutex, &abstime); PRT("ret : %d", ret); if (ret == ETIMEDOUT) { PRT("Timedlock... ETIMEDOUT"); break; } ret = pthread_mutex_unlock(&mutex); if (ret != 0) PRT("ERR : %d", ret); sleep(1); } while(1); PRT("Unlock pp Mutex"); ret = pthread_mutex_unlock(&pp); if (ret != 0) PRT("ERR : %d", ret); PRT("End Parent"); } int main(int argc, char *argv[]) { pthread_t tid0, tid1; pthread_mutexattr_t mutexAttributes; int ret; ret = pthread_mutexattr_init(&mutexAttributes); assert(ret == 0); ret = pthread_mutexattr_setpshared(&mutexAttributes, PTHREAD_PROCESS_SHARED); assert(ret == 0); ret = pthread_mutexattr_setrobust(&mutexAttributes, PTHREAD_MUTEX_ROBUST); assert(ret == 0); ret = pthread_mutexattr_settype(&mutexAttributes, PTHREAD_MUTEX_RECURSIVE); assert(ret == 0); PRT("Init Mutex"); ret = pthread_mutex_init(&mutex, &mutexAttributes); ret = pthread_mutexattr_destroy(&mutexAttributes); assert(ret == 0); ret = pthread_create(&tid0, NULL, child, NULL); ret = pthread_create(&tid1, NULL, parent, NULL); pthread_join(tid0, NULL); pthread_join(tid1, NULL); ret = pthread_mutex_destroy(&mutex); assert(ret == 0 || ret == EBUSY); return 0; }