sem_timedwait在RedHat Enterprise Linux 5.3及更高版本上不正确支持吗? [英] sem_timedwait not supported properly on RedHat Enterprise Linux 5.3 onwards?

查看:146
本文介绍了sem_timedwait在RedHat Enterprise Linux 5.3及更高版本上不正确支持吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在带有pthreads sem_timedwait的RedHat Enterprise Linux系统上,我们看到了奇怪的行为.仅从5.3版开始.

We're seeing odd behaviour on RedHat Enterprise Linux systems with pthreads sem_timedwait. It's only occurring with versions 5.3 onwards.

当我们使用sem_init在后台线程上创建信号量时,不会返回任何错误.当我们执行sem_timedwait时,我们会立即返回errno = 38(ENOSYS),表明它不受支持.

When we create the semaphore on a background thread with sem_init, no error is returned. When we do sem_timedwait, we get an immediate return with errno = 38 (ENOSYS) indicating it's not supported.

如果我们在主线程上执行相同的操作,则它将按预期工作,并且不会从sem_timedwait中得到任何错误.

If we do the same thing on the main thread, it works as expected and we get no error from sem_timedwait.

我们在RHEL 5.2或更低版本上看不到它.我们尝试使用gcc 3.2.3和4.1.2编译代码并获得相同的结果,因此这似乎是运行时问题.

We don't see it on RHEL 5.2 or before. We've tried compiling our code with gcc 3.2.3 and 4.1.2 and get the same result, so it seems to be a run-time issue.

所以,我的问题(最后是;)

So, my questions (finally ;)

1)其他人看到了吗? 2)RHEL 5.3及更高版本是否是已知问题? 3)我们正在使用sem_timedwait来休眠一个线程. Linux上有什么替代品可以做同样的事情?

1) has anyone else seen this? 2) is it a known issue with RHEL 5.3 onwards? 3) we're using sem_timedwait to sleep a single thread. What alternatives are there on Linux to do the same thing?

如果这是另一个问题的重复,请告诉我.我看过但找不到相同的问题,只是OSX的相似问题,这不是我们正在使用的.

If this is a duplicate of another question, let me know. I've looked but can't find one with the same question, just similar ones for OSX which isn't what we're using.

谢谢, pxb

更新:刚刚进行了更多测试,结果如下:

Update: just done some more testing with the following results:

  • 如果我在RHEL5.4框(带有-L/usr/lib64和-lstdc ++ -lrt)上使用gcc 4.1.2进行64位构建,并在RHEL5的64位安装上运行,则可以正常工作
  • 如果我在RHEL5.1框(带有-L/usr/lib和-lstdc ++ -lrt)上使用gcc 4.1.2进行32位构建,然后在完全相同的64位RHEL5框上运行它,我们得到sem_timedwait中的ENOSYS错误

因此,RHEL5.4(和看似RHEL5.3)的64位和32位运行时库之间似乎有所不同.唯一的不同是RHEL5.1和RHEL5.4盒分别完成了32位和64位构建.

So, it appears to be a difference between the 64 and 32 bit runtime libs on RHEL5.4 (and seemingly RHEL5.3). The only other difference was that the 32 and 64 bit builds were done of RHEL5.1 and RHEL5.4 boxes respectively.

推荐答案

最后找出问题所在.在RHEL 5.4上,如果我们调用sem_init,然后执行sem_timedwait,则会得到定时等待的某种随机行为,具体取决于代码所在的位置,拥有sem_t的对象是在堆还是在堆栈等.有时,定时等待会立即返回errno = 38(ENOSYS),有时它会在返回之前正确等待.

Finally found out what the issue is. On RHEL 5.4 if we call sem_init then do sem_timedwait we get somewhat random behaviour of the timed wait, depending on where the code is located, whether the object that owns the sem_t is on the heap or stack, etc. Sometimes the timed wait returns immediately with errno = 38 (ENOSYS), sometimes it waits correctly before returning.

通过valgrind运行它会出现此错误:

Running it via valgrind gives this error:

==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)

如果我在RHEL 5.2上运行完全相同的代码,问题将消失,并且valgrind不会报告任何错误.

If I run exactly the same code on RHEL 5.2 the problem goes away and valgrind reports no errors.

如果我在调用sem_init之前在sem_t变量上执行了memset,则问题在RHEL 5.4上消失了

If I do a memset on the sem_t variable before calling sem_init the problem goes away on RHEL 5.4

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

因此,似乎RHEL5.4上的信号量或它在内部使用的东西中引入了一个错误,并且sem_init无法正确初始化sem_t内存.或者,sem_timed等待已更改为以前所未有的方式对此敏感.

So, it looks like a bug has been introduced with semaphores on RHEL5.4 or something that it uses internally, and sem_init isn't correctly initialising the sem_t memory. Or, sem_timed wait has changed to be sensitive to this in a way it wasn't before.

有趣的是,在任何情况下sem_init都不会返回错误来表明它无法正常工作.

Interestingly, in no cases does sem_init return an error to indicate it didn't work though.

或者,如果预期的行为是sem_init不会初始化sem_t的内存,而这取决于调用者,那么该行为肯定已随RHEL 5.4改变

Alternatively, if the expected behaviour is that sem_init won't intialise the memory of sem_t and that's up to the caller, then the behaviour has certainly changed with RHEL 5.4

pxb

更新-这是测试用例代码,以防万一其他人想尝试一下.请注意,仅当从.so调用sem_timedwait时才出现问题,并且只有RHEL5.4(也许5.3尚未测试过),并且仅当构建为32位二进制文​​件时(当然是与32位库链接)

Update - here's the test case code in case anyone else wants to try it. Note the problem only occurs when sem_timedwait is called from a .so, and only RHEL5.4 (maybe 5.3 haven't tested it), and only when built as a 32 bit binary (linking against 32 bit libs of course)

1)

#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)在main.cpp中(请注意重复的测试功能,以便我们可以比较.so和exe中的运行情况)

2) in main.cpp (note the duplicate test function so we can compare running from within the .so with in the exe)

#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)这是Makefile

3) here's the Makefile

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

测试用例是:

  1. 从.so内部运行,无需执行memset
  2. 从.so内部运行并执行memset
  3. 从exe内部运行,无需执行memset
  4. 从exe中运行并执行memset

这是在RHEL5.4上运行的结果

And here's the result running on 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返回.

You can see that case 1 returns immediately with errno = 38.

如果我们在RHEL5.2上运行完全相同的代码,则会得到以下信息:

If we run the exact same code on RHEL5.2 we get the following:

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

您可以看到所有案例现在都能按预期工作!

You can see that all cases now work as expected!

这篇关于sem_timedwait在RedHat Enterprise Linux 5.3及更高版本上不正确支持吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆