2017-09-22 17 views
2

マルチスレッドアクセスから関数を保護したい。その目的のために私はpthread_mutex_tミューテックスを使用しています。私は関数の始めにそれをロックしようとし、関数を実行してから再び解放します。ミューテックスが使用されている場合、ミューテックスが使用可能になるまで最大60秒間待機する必要があります。それでもまだ使用できない場合、関数は失敗するはずです。タイムアウトを待つことなくpthread_mutex_timedlock()が早期に終了する

私が抱えている問題は、pthread_mutex_timedlockがタイムアウト値を完全に無視しているようです。私は60秒のタイムアウトを指定しますが、ロックが取られれば、関数は実際には待たずにエラーコードETIMEDOUTで直ちに戻ります。

問題を再現するための最小限の例を示します。この場合、同じスレッドから複数回ロックしようとしていないので、再帰的または非再帰的なmutexを使用しているかどうかは関係ありません。

#include <stdlib.h> 
#include <stdio.h> 
#include <stdint.h> 
#include <stdbool.h> 
#include <string.h> 
#include <stddef.h> 
#include <unistd.h> 
#include <time.h> 
#include <errno.h> 
#include <pthread.h> 

pthread_mutex_t lock; /* exclusive lock */ 

//do some work to keep the processor busy.. 
int wut() { 
    int x = 0; 
    for(int i=0; i < 1024*1024*1024; i++) 
     x += 1; 
    return x; 
} 

void InitMutex(){ 
    /*pthread_mutexattr_t Attr; 
    pthread_mutexattr_init(&Attr); 
    pthread_mutexattr_settype(&Attr, PTHREAD_MUTEX_RECURSIVE); 
    pthread_mutex_init(&lock, &Attr);*/ 
    pthread_mutex_init(&lock, NULL); 
} 

//lock mutex, wait at maximum 60 seconds, return sucesss 
int LockMutex() { 
    struct timespec timeoutTime; 
    timeoutTime.tv_nsec = 0; 
    timeoutTime.tv_sec = 60; 
    printf("Nanoseconds: %lu, seconds %lu\n", timeoutTime.tv_nsec, timeoutTime.tv_sec); 
    int retVal = pthread_mutex_timedlock(&lock, &timeoutTime); 
    printf("pthread_mutex_timedlock(): %d\n", retVal); 
    if(retVal != 0) { 
     const char* errVal = NULL; 
     switch(retVal) { 
     case EINVAL: errVal = "EINVAL"; break; 
     case EAGAIN: errVal = "EAGAIN"; break; 
     case ETIMEDOUT: errVal = "ETIMEDOUT"; break; 
     case EDEADLK: errVal = "EDEADLK"; break; 
     default: errVal = "unknown.."; break; 
     } 
     printf("Error taking lock in thread %lu: %s (%s)\n", pthread_self(), errVal , strerror(retVal)); 
    } 
    return retVal == 0; //indicate success/failure 
} 

void UnlockMutex() { 
    pthread_mutex_unlock(&lock); 
} 

void TestLockNative() { 
    uint64_t thread_id = pthread_self(); 
    printf("Trying to take lock in thread %lu.\n", thread_id); 
    int ret = LockMutex(); 
    printf("Got lock in thread %lu. sucess=%d\n", thread_id, ret); 
    wut(); 
    printf("Giving up lock now from thread %lu.\n", thread_id); 
    UnlockMutex(); 

} 

void* test_thread(void* arg) { 
    //TestLock(); 
    TestLockNative(); 
    return NULL; 
} 

int main() { 
    InitMutex(); 
    //create two threads which will try to access the protected function at once 
    pthread_t t1, t2; 
    pthread_create(&t1, NULL, &test_thread, NULL); 
    pthread_create(&t2, NULL, &test_thread, NULL); 

    //wait for threads to end 
    pthread_join(t1, NULL); 
    pthread_join(t2, NULL); 

    return 0; 
} 

プログラムの出力は、例えば:gcc -o test test.c -lpthread

Trying to take lock in thread 139845914396416. 
Nanoseconds: 0, seconds 6000 
pthread_mutex_timedlock(): 0 
Got lock in thread 139845914396416. sucess=1 
Trying to take lock in thread 139845906003712. 
Nanoseconds: 0, seconds 6000 
pthread_mutex_timedlock(): 110 
Error taking lock in thread 139845906003712: ETIMEDOUT (Connection timed out) [<-- this occurs immediately, not after 60 seconds] 
Got lock in thread 139845906003712. sucess=0 
Giving up lock now from thread 139845906003712. 

コンパイルが動作するはずです。

だから誰でもここで何が起こっているのか、なぜpthread_mutex_timedlock()は私のタイムアウト値を無視するのですか? the way it is documentedはまったく動作しません。

私はgccでコンパイルしたUbuntu 16.04.2 LTSシステムを使用しています。

答えて

5

pthread_mutex_timedlockのマニュアルページは言う:abstimeで指定された絶対時間が経過するとタイムアウトがそこで

をベースとするクロック、使用して を測定すると

タイムアウトが、満了しますあなたのタイムアウト値を指定するリアルタイム:

int LockMutex() { 
    struct timespec timeoutTime; 
    clock_gettime(CLOCK_REALTIME, &timeoutTime); 
    timeoutTime.tv_sec += 60; 

    int retVal = pthread_mutex_timedlock(&lock, &timeoutTime); 
    .... 
+0

単純な言葉ではなく、むしろパラメタを読むことができませんr値またはドキュメントのこの行でこの問題が発生しました。どうもありがとうございました。 –

+0

私は助けることができる嬉しい:) – LWimsey

関連する問題