gpt4 book ai didi

c - sem_timedwait 在 RedHat Enterprise Linux 5.3 及更高版本上不被正确支持?

转载 作者:IT王子 更新时间:2023-10-29 01:15:19 26 4
gpt4 key购买 nike

我们在 RedHat Enterprise Linux 系统上看到带有 pthreads sem_timedwait 的奇怪行为。它仅在 5.3 及更高版本中出现。

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

如果我们在主线程上做同样的事情,它会按预期工作,并且我们不会从 sem_timedwait 中得到任何错误。

我们在 RHEL 5.2 或更早版本上看不到它。我们已经尝试使用 gcc 3.2.3 和 4.1.2 编译我们的代码并得到相同的结果,所以这似乎是一个运行时问题。

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

1) 还有其他人看到了吗?2) 这是 RHEL 5.3 以后的已知问题吗?3) 我们正在使用 sem_timedwait 使单个线程休眠。在 Linux 上有哪些替代方案可以做同样的事情?

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

谢谢,

更新:刚刚做了一些更多的测试,结果如下:

  • 如果我在 RHEL5.4 机器上使用 gcc 4.1.2 进行 64 位构建(使用 -L/usr/lib64 和 -lstdc++ -lrt)并在 64 位安装的 RHEL5 上运行它,它工作正常<
  • 如果我在 RHEL5.1 机器上使用 gcc 4.1.2 进行 32 位构建(使用 -L/usr/lib 和 -lstdc++ -lrt)并在完全相同的 64 位 RHEL5 机器上运行它,我们得到来自 sem_timedwait 的 ENOSYS 错误

因此,这似乎是 RHEL5.4(似乎是 RHEL5.3)上 64 位和 32 位运行时库之间的区别。唯一的区别是 32 位和 64 位构建分别是在 RHEL5.1 和 RHEL5.4 机器上完成的。

最佳答案

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

通过 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)

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

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

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

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

有趣的是,sem_init 在任何情况下都不会返回一个错误来表明它没有工作。

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

pxb

更新 - 这是测试用例代码,以防其他人想尝试。请注意,仅当从 .so 调用 sem_timedwait 时才会出现此问题,并且仅在 RHEL5.4(可能 5.3 尚未对其进行测试)时出现,并且仅当构建为 32 位二进制文​​件时(当然链接到 32 位库)

1) 在 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) 在 main.cpp 中(注意重复的测试函数,以便我们可以比较从 .so 和 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) 这是生成文件

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 上运行的结果

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

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

关于c - sem_timedwait 在 RedHat Enterprise Linux 5.3 及更高版本上不被正确支持?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1832395/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com