2010-12-06 13 views
1

EDIT3:新しいスレッドが必要になるたびに生成されます。「入力」は、内部で解放されたchar *のコピーです。 cURL関数がスレッドセーフであると仮定します。この関数はスレッドセーフですか?

EDIT4:目に見えない関数はスレッドセーフであると仮定します。

static void *Com_GoogleTranslate(void* input) { 

CURL *easy_handle; 
char *pos1, *pos2, url[1024], final[1024], inlang[8], outlang[8], *encoded; 
const int const_strlen = strlen("\"translatedText\":\""); 
struct GoogleMem chunk; 

pthread_mutex_lock(&GoogleMessage_mutex); 
    // 'auto' is really empty in google API: 
    if (!strcmp(clu.translateIn->string, "auto")) 
    strcpy(inlang, ""); 
    else    
    strcpy(inlang, clu.translateIn->string); 

    if (!strcmp(clu.translateOut->string, "auto")) 
    strcpy(outlang, ""); 
    else    
    strcpy(outlang, clu.translateOut->string); 
pthread_mutex_unlock(&GoogleMessage_mutex); 

// Build the URL 
url[0] = '\0'; 
strcat(url, "http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q="); 

// Encode input into URL formatting 
encoded = url_encode((char*)input); 
if (!encoded) return 0; 

strcat(url, encoded); 
strcat(url, "&langpair="); 
strcat(url, inlang); 
strcat(url, "|"); 
strcat(url, outlang); 

chunk.memory = malloc(1); // realloc grows it at Com_GoogleTranslateMem() 
if (!chunk.memory) return 0; 
chunk.size = 0; // no data yet 

// cURL initialization for this sub-session: 
easy_handle = qcurl_easy_init(); 

// ioq3-urt: was needed on https:// (v2 API) attempts when using GnuTLS 
//qcurl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, 3); 

// set URL: 
qcurl_easy_setopt(easy_handle, CURLOPT_URL, url); 

// ioq3-urt: required for multithreading according to cURL doc. 
qcurl_easy_setopt(easy_handle, CURLOPT_NOSIGNAL, 1); 

// ioq3-urt: skip peer verification; required for google translate when SSL was used 
//qcurl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L); 

// send all data to this function 
qcurl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, Com_GoogleTranslateMem); 

// we pass our 'chunk' struct to the callback function: 
qcurl_easy_setopt(easy_handle, CURLOPT_WRITEDATA, (void *)&chunk); 

// some servers don't like requests that are made without a user-agent field, so we provide one: 
qcurl_easy_setopt(easy_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0"); 

// ioq3-urt: Required by Google Translate terms: 
qcurl_easy_setopt(easy_handle, CURLOPT_REFERER, "ioq3-urt"); 

// fetch it 
qcurl_easy_perform(easy_handle); 

// cleanup curl stuff 
qcurl_easy_cleanup(easy_handle); 

/* 
    Now chunk.memory points to a memory block that is chunk.size 
    bytes big and contains the remote file. 

    Nothing has yet deallocated that data, hence free() is used at the end. 
*/ 

if (!chunk.size) { 
    pthread_mutex_lock(&GoogleMessage_mutex); 
    sprintf(GoogleMessage.message, "Translation: no data received from Google\n"); 
    GoogleMessage.new_message = qtrue; 
    pthread_mutex_unlock(&GoogleMessage_mutex); 
    // Free up memory (same with the end) 
    if(chunk.memory) free(chunk.memory); 
    free(encoded); 
    free(input); 
    return 0; 
} 

if ((pos1 = strstr(chunk.memory, "\"translatedText\":\""))) { // Make sure we use a valid file: 

    pos2 = strstr(pos1 + const_strlen, "\""); // position translated text ends 

    // Build the translated text: 
    final[0] = '\0'; 
    strncat(final, pos1 + const_strlen, strlen(pos1) - (strlen(pos2) + const_strlen)); 

    // Final printing of the translated text: 
    pthread_mutex_lock(&GoogleMessage_mutex); 
    sprintf(GoogleMessage.message, "^2Translated^7: ^3%s\n", final); 
    GoogleMessage.new_message = qtrue; 
    pthread_mutex_unlock(&GoogleMessage_mutex);  
    #ifdef BUILD_FREETYPE 
    TTF_Find_Slot(final, clu.TTF_MessageMaxTime->integer); 
    #endif 

} else { 
    pthread_mutex_lock(&GoogleMessage_mutex); 
    sprintf(GoogleMessage.message, "Translation: no valid translation file received from Google\n"); 
    GoogleMessage.new_message = qtrue; 
    pthread_mutex_unlock(&GoogleMessage_mutex); 
} 

// Free allocated memory 
if(chunk.memory) free(chunk.memory); 
free(encoded); 
free(input); 
return 0; 
} 

私は、特定のシステム上の不安定な挙動を取得していると私はその疑わしいハードウェア(インテルOpenGLを?)疑いながら、私は何かを欠場かどうかを確認したいと思います。

EDIT:cURL自体がスレッドセーフであるとします。

EDIT2: "input"はこのスレッドに解放された新しいコピーです。

+0

インテルとOpenGLとの接続は何ですか? –

+0

これはゲームで実行されます(SDL OpenGLコンテキストで実行されます)。 OpenGLのインテルは、OpenGLのプログラマーには恐ろしい、恐ろしい、恐ろしい評判を与えているが、これでもそれを疑う余地はない。 –

答えて

1

mutexで保護されたセクションの外で呼び出すすべての関数自体がスレッドセーフである限り、スレッドセーフであることがわかります。

しかし、mallocのスレッドの安全性に関して疑問があります。 this questionを参照してください。

+0

さて、私はgccだけでコンパイルしています。 –

+0

mallocについて興味があります。マルチスレッド化すると、それほど厄介なことになります。これらのOpenMPなどのAPIは、結局のところ便利です。 –

1

これはスレッドセーフの問題ではありませんが、潜在的な問題として顕著なものが1つあります。 chunk.memory値がstrncat内のその値に"translatedText":"値以下の別の二重引用符が含まれている、それがnullになり、その後のstrlen()なかった場合

pos2 = strstr(pos1 + const_strlen, "\""); // position translated text ends 

:次のコード行は、成功した検索のためのチェックを持っていませんアクセス違反が発生する可能性があります。

assertを追加することは、少なくともそれが常に成功していることを確認するために最低でも問題ありません。しかし、私は他の機能が何をしているのか分かりません。二重引用符が文字列内にあることを保証すれば、これは問題ではありません。

また、「関連するデータについて何も知らない」という問題は、すべて1024バッファに収まる文字列長についての盲目的な仮定です。防御的なコーディングの観点からは、これらの呼び出しに対する追加のチェックが害を及ぼすことはありません。

それ以外の場合は、JeremyPとの間では、指定されたコードに基づいてスレッドセーフであると私は同意します(+1)。

関連する問題