2009-12-02 7 views
5

हम RedHat Enterprise Linux सिस्टम पर pddreads sem_timedwait के साथ अजीब व्यवहार देख रहे हैं। यह केवल संस्करण 5.3 के साथ होता है।sem_timedwait RedHat Enterprise Linux 5.3 के बाद ठीक से समर्थित नहीं है?

जब हम sem_init के साथ पृष्ठभूमि थ्रेड पर सेमफोर बनाते हैं, तो कोई त्रुटि वापस नहीं आती है। जब हम sem_timedwait करते हैं, तो हमें errno = 38 (ENOSYS) के साथ तत्काल वापसी मिलती है जो दर्शाती है कि यह समर्थित नहीं है।

यदि हम मुख्य धागे पर एक ही काम करते हैं, तो यह अपेक्षित काम करता है और हमें sem_timedwait से कोई त्रुटि नहीं मिलती है।

हम इसे RHEL 5.2 या इससे पहले नहीं देखते हैं। हमने जीसीसी 3.2.3 और 4.1.2 के साथ हमारे कोड को संकलित करने का प्रयास किया है और यह एक ही परिणाम प्राप्त करता है, इसलिए यह एक रन-टाइम समस्या प्रतीत होता है।

तो, मेरे सवालों का (अंत में;)

1) किसी और को इस देखा है? 2) क्या यह आरएचईएल 5.3 के बाद एक ज्ञात मुद्दा है? 3) हम एक धागे को सोने के लिए sem_timedwait का उपयोग कर रहे हैं। लिनक्स पर एक ही काम करने के लिए क्या विकल्प हैं?

यदि यह किसी अन्य प्रश्न का डुप्लिकेट है, तो मुझे बताएं। मैंने देखा है लेकिन एक ही प्रश्न के साथ एक नहीं मिल सकता है, ओएसएक्स के लिए समान ही है जो हम उपयोग नहीं कर रहे हैं।

धन्यवाद, pxb

अद्यतन: बस निम्नलिखित परिणामों के साथ कुछ और परीक्षण किया:

  • अगर मैं एक RHEL5.4 बॉक्स पर जीसीसी 4.1.2 का उपयोग कर एक 64 बिट का निर्माण करते हैं (साथ -एल/​​usr/lib64 और -lstdC++ -lrt) और इसे RHEL5 के 64 बिट इंस्टॉल पर चलाएं, यह ठीक है
  • यदि मैं एक RHEL5.1 बॉक्स पर जीसीसी 4.1.2 का उपयोग करके 32 बिट बिल्ड करता हूं (एलएल के साथ/usr/lib और -lstdC++ -lrt) और इसे ठीक उसी 64 बिट RHEL5 बॉक्स पर चलाएं, हमें sem_timedwait
  • से ENOSYS त्रुटियां मिलती हैं

तो, यह RHEL5.4 (और प्रतीत होता है RHEL5.3) पर 64 और 32 बिट रनटाइम libs के बीच एक अंतर प्रतीत होता है। एकमात्र अन्य अंतर यह था कि 32 और 64 बिट बिल्ड क्रमश: आरएचईएल 5.1 और आरएचईएल 5.4 बक्से से किए गए थे।

+0

इसे ठीक करने के लिए प्रबंधित, लेकिन मुझे यकीन नहीं है कि फिक्स कैसे काम करता है। कोड जो सेमफोर फ़ंक्शंस को कॉल करता है वह एक वर्ग में एक वर्ग में था, और इन्हें निष्पादन योग्य से ही बुलाया जा रहा था। यदि हम कोड को सीपीपी फ़ाइल से हेडर पर ले जाते हैं (यानी प्रभावी रूप से निष्पादन योग्य में वर्ग को इनलाइन करते हैं) तो समस्या गायब हो जाती है। तो, ऐसा लगता है: RHEL5.4 पर अगर हम sem_timedwait को भीतर से कॉल करते हैं तो यह विफल हो जाता है, लेकिन अगर हम निष्पादन योग्य से एक ही कॉल करते हैं तो यह काम करता है। और मुझे नहीं पता कि क्यों ... – pxb

उत्तर

6

अंत में पता चला कि समस्या क्या है। आरएचईएल 5.4 पर अगर हम sem_init को कॉल करते हैं तो sem_timedwait करें, हम समय के इंतजार के कुछ यादृच्छिक व्यवहार प्राप्त करते हैं, इस पर निर्भर करता है कि कोड कहां स्थित है, चाहे ऑब्जेक्ट जो sem_t का मालिक है ढेर या ढेर आदि पर है। कभी-कभी समय प्रतीक्षा प्रतीक्षा तुरंत errno = 38 (ENOSYS) के साथ, कभी-कभी यह लौटने से पहले ठीक से इंतजार कर रहा है। अगर मैं RHEL 5.2 पर ठीक उसी कोड को चलाने समस्या दूर और valgrind रिपोर्ट कोई त्रुटि हो जाता है

==32459== Thread 2: 
==32459== Syscall param futex(op) contains uninitialised byte(s) 
==32459== at 0x406C78: sem_timedwait (in /lib/libpthread-2.5.so) 
==32459== by 0x8049F2E: TestThread::Run() (in /home/stsadm/semaphore_test/semaphore_test) 
==32459== by 0x44B2307: nxThread::_ThreadProc(void*) (in /home/stsadm/semaphore_test/libcore.so) 
==32459== by 0x4005AA: start_thread (in /lib/libpthread-2.5.so) 
==32459== by 0x355CFD: clone (in /lib/libc-2.5.so) 

:

valgrind के माध्यम से यह चल रहा है इस त्रुटि देता है।

मैं sem_init कॉल समस्या RHEL पर चली जाती है 5,4

memset(&_semaphore, 0, sizeof(sem_t)); 

तो, ऐसा लगता है कि एक बग की तरह या RHEL5.4 पर संकेतबाहु कुछ के साथ शुरू किया गया है से पहले sem_t चर पर एक memset करते हैं यह है कि आंतरिक रूप से उपयोग करता है, और sem_init sem_t स्मृति को सही ढंग से प्रारंभ नहीं कर रहा है। या, sem_timed प्रतीक्षा इस तरह से संवेदनशील होने के लिए बदल गया है जिस तरह से पहले नहीं था।

दिलचस्प बात यह है कि, किसी भी मामले में sem_init यह इंगित करने के लिए एक त्रुटि देता है कि यह काम नहीं करता है।

या फिर, यदि अपेक्षित व्यवहार कि sem_init sem_t की स्मृति intialise नहीं होगा और कहा कि फोन करने वाले पर निर्भर है, तो निश्चित रूप से व्यवहार RHEL 5.4

pxb

अद्यतन के साथ बदल गया है - यहाँ है अगर कोई और कोशिश करना चाहता है तो टेस्ट केस कोड। ध्यान दें कि समस्या तब होती है जब sem_timedwait को .so से कहा जाता है, और केवल RHEL5.4 (शायद 5.3 ने इसका परीक्षण नहीं किया है), और केवल 32 बिट बाइनरी के रूप में बनाया गया है (पाठ्यक्रम के 32 बिट libs के खिलाफ लिंक)

1) main.cpp में semtest.cpp

#include <semaphore.h> 
#include <stdio.h> 
#include <string.h> 
#include <errno.h> 
#include <time.h> 

void semtest(int semnum, bool initmem) 
{ 
     sem_t sem; 

     if (initmem) 
     { 
       memset(&sem, 0, sizeof(sem_t)); 
       printf("sem %d: memset size = %d\n", semnum, sizeof(sem_t)); 
     } 

     errno = 0; 
     int res = sem_init(&sem, 0, 0); 

     printf("sem %d: sem_init res = %d, errno = %d\n", semnum, res, errno); 

     timespec ts; 
     clock_gettime(CLOCK_REALTIME, &ts); 
     ts.tv_sec += 1; 

     errno = 0; 
     res = sem_timedwait(&sem, &ts); 

     printf("sem %d: sem_timedwait res = %d, errno = %d\n\n", semnum, res, errno); 
} 

2) में (डुप्लिकेट परीक्षण समारोह ध्यान दें तो हम exe में साथ .so के भीतर से चल तुलना कर सकते हैं)

#include <semaphore.h> 
#include <stdio.h> 
#include <string.h> 
#include <errno.h> 
#include <time.h> 

extern void semtest(int semnum, bool initmem); 

void semtest_in_exe(int semnum, bool initmem) 
{ 
     sem_t sem; 

     if (initmem) 
     { 
       memset(&sem, 0, sizeof(sem_t)); 
       printf("sem %d: memset size = %d\n", semnum, sizeof(sem_t)); 
     } 

     errno = 0; 
     int res = sem_init(&sem, 0, 0); 

     printf("sem %d: sem_init res = %d, errno = %d\n", semnum, res, errno); 

     timespec ts; 
     clock_gettime(CLOCK_REALTIME, &ts); 
     ts.tv_sec += 1; 

     errno = 0; 
     res = sem_timedwait(&sem, &ts); 

     printf("sem %d: sem_timedwait res = %d, errno = %d\n\n", semnum, res, errno); 
} 

int main(int argc, char* argv[], char** envp) 
{ 
     semtest(1, false); 
     semtest(2, true); 
     semtest_in_exe(3, false); 
     semtest_in_exe(4, true); 
} 

3) मेकफ़ाइल

है 210
all: main 

semtest.o: semtest.cpp 
     gcc -c -fpic -m32 -I /usr/include/c++/4.1.2 -I /usr/include/c++/4.1.2/i386-redhat-linux semtest.cpp -o semtest.o 

libsemtest.so: semtest.o 
     gcc -shared -m32 -fpic -lstdc++ -lrt semtest.o -o libsemtest.so 

main: libsemtest.so 
     gcc -m32 -L . -lsemtest main.cpp -o semtest 

परीक्षण मामलों हैं: .so के भीतर से memset

  • रन कर बिना

    1. .so के भीतर से चलाने के लिए और exe के भीतर से memset
    2. रन कर
    3. रन से memset
    4. कर के बिना exe के भीतर और memset

    और यहां परिणाम RHEL5.4

    पर चल रहा है
    sem 1: sem_init res = 0, errno = 0 
    sem 1: sem_timedwait res = -1, errno = 38 
    
    sem 2: memset size = 16 
    sem 2: sem_init res = 0, errno = 0 
    sem 2: sem_timedwait res = -1, errno = 110 
    
    sem 3: sem_init res = 0, errno = 0 
    sem 3: sem_timedwait res = -1, errno = 110 
    
    sem 4: memset size = 16 
    sem 4: sem_init res = 0, errno = 0 
    sem 4: sem_timedwait res = -1, errno = 110 
    

    आप 1 रिटर्न तुरंत errno साथ उस मामले को देख सकते हैं = 38.

    हम RHEL5.2 पर ठीक उसी कोड को चलाने, तब हम निम्नलिखित मिलती है:

    sem 1: sem_init res = 0, errno = 0 
    sem 1: sem_timedwait res = -1, errno = 110 
    
    sem 2: memset size = 16 
    sem 2: sem_init res = 0, errno = 0 
    sem 2: sem_timedwait res = -1, errno = 110 
    
    sem 3: sem_init res = 0, errno = 0 
    sem 3: sem_timedwait res = -1, errno = 110 
    
    sem 4: memset size = 16 
    sem 4: sem_init res = 0, errno = 0 
    sem 4: sem_timedwait res = -1, errno = 110 
    

    आप देख सकते हैं कि सभी मामलों अब उम्मीद के रूप में काम करते हैं!

  • +0

    +1 अनुवर्ती – pmg

    +0

    धन्यवाद के लिए धन्यवाद, मेरी मदद भी की। लेकिन मैं उबंटू 9 .10 पर था। कोड पहले काम कर रहा था, बस थोड़ा बदलाव तोड़ दिया (इरनो 38 के साथ विफल होना शुरू किया)। और स्मृति ने समस्या हल की। – inazaruk

    2

    ऐसा नहीं है कि semtest बुला रहा है [email protected]_2.1, और libsemtest.so[email protected]_2.0 बुला रहा है लगता है।

    sem_timedwait() संस्करण 2.1 की आवश्यकता है।

    मुझे -lpthread को libsemtest.so बनाने वाले नियम में सभी चार परीक्षणों के लिए सही परिणाम मिल गए हैं।

    मैंने इसका परीक्षण आरएच 5.3 पर किया है।

    +1

    यह वास्तव में सही दृष्टिकोण है (स्वीकृत उत्तर नहीं है)। –

    +0

    इस तरह की विसंगति क्यों और कैसे होती है? प्रत्येक पुस्तकालय को lpthread के खिलाफ जोड़ने का एकमात्र तरीका यह सुनिश्चित करने के लिए है कि वे लगातार हैं? – KyleL