- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我们在 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(似乎是 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
测试用例是:
这是在 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/
我正在阅读有关sem_timedwait()的手册,但无法弄清楚该示例。我目前的理解是: 如果 sem_timedwait() 超时,则返回 -1 并将 errno 设置为 ETIMEDOUT。因此我
我写了一个小类,封装了共享锁和共享信号量。这些类通过了我所有的单元测试,除了一个:大约 60% 的时间使用 sem_timedwait 锁定共享内存信号量失败。这是我的代码: SharedLock::
我想在信号量上等待 20 英里秒,如下所示,但是当我打印 tv_sec 和 tv_nsec 的值时,它们的值变得非常大。 任何人都可以帮助理解下面的代码。 if (clock_gettime(CLOC
如果 10 秒后它不能减少信号量(另一个线程可以或不能增加它),我试图让我的程序中的线程停止我看到我可以为此使用 sem_timedwait() 但我无法在网上找到一个好的例子。所以我只想替换这个:
我使用 eCos 开发嵌入式系统:我在同一进程中有 2 个线程和 1 个信号量。 线程 A 将信号量初始化为 0,以便第一次尝试获取信号量时将被阻止。 线程 A 向线程 B 发送命令,并提供回调。 线
我尝试在 AIX 中使用 sem_timedwait。 我收到此错误: *“ld:0711-317 错误: undefined symbol :.sem_timedwait”* 我可以猜到,我缺少一些
我有 3 个进程需要同步。进程一做某事然后唤醒进程二并休眠,进程二做某事然后唤醒进程三并休眠,进程三做某事并唤醒进程一并休眠。整个循环定时运行大约 25hz(由外部同步到进程一之前触发我的“真实”应用
假设我有一个程序使用 sem_timedwait 等待 100 毫秒(获取当前时间,加上 100 毫秒,将结果用作 abs_timeout,cf. man page ).现在碰巧系统时间在等待信号量时
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout); 的示例代码使用 CLOCK_REALTIME 作为 clock_g
我正在尝试使用 sem_timedwait() 重复锁定和解锁信号量。基于示例 here ,我通过以下方式将我的结构 timespec 设置为 20 毫秒超时: sem_t semaphore; /
我正在尝试将一个使用信号量的项目(来自 linux)移植到 Mac OS X 但是一些 posix 信号量没有在 Mac OS X 上实现 我在这个端口打到的一个是 sem_timedwait() 我
我们在 RedHat Enterprise Linux 系统上看到带有 pthreads sem_timedwait 的奇怪行为。它仅在 5.3 及更高版本中出现。 当我们使用 sem_init 在后
我是一名优秀的程序员,十分优秀!