अंत में पता चला कि समस्या क्या है। आरएचईएल 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
रन कर बिना
- .so के भीतर से चलाने के लिए और exe के भीतर से memset
- रन कर
- रन से memset
कर के बिना 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
आप देख सकते हैं कि सभी मामलों अब उम्मीद के रूप में काम करते हैं!
इसे ठीक करने के लिए प्रबंधित, लेकिन मुझे यकीन नहीं है कि फिक्स कैसे काम करता है। कोड जो सेमफोर फ़ंक्शंस को कॉल करता है वह एक वर्ग में एक वर्ग में था, और इन्हें निष्पादन योग्य से ही बुलाया जा रहा था। यदि हम कोड को सीपीपी फ़ाइल से हेडर पर ले जाते हैं (यानी प्रभावी रूप से निष्पादन योग्य में वर्ग को इनलाइन करते हैं) तो समस्या गायब हो जाती है। तो, ऐसा लगता है: RHEL5.4 पर अगर हम sem_timedwait को भीतर से कॉल करते हैं तो यह विफल हो जाता है, लेकिन अगर हम निष्पादन योग्य से एक ही कॉल करते हैं तो यह काम करता है। और मुझे नहीं पता कि क्यों ... – pxb