题
我有一个带有信号量的队列。在某个时刻,所有的调用 sem_post()
尽管信号量本身有效,但始终返回“无效参数”错误
信号量是C++对象的私有成员,永远不会被删除,也可以在gdb中检查。我添加了 sem_getvalue()
就在之前 sem_post()
- 值读取正常,然后失败 sem_post()
. 。可能出什么问题了?
CThreadQueue::CThreadQueue(int MaxSize) :
_MaxSize(MaxSize)
{
sem_init(&_TaskCount, 0, 0)
pthread_mutex_init(&_Mutex, 0);
pthread_create(&_Thread, NULL, CThreadQueue::StartThread, this);
}
CThreadQueue::~CThreadQueue()
{
pthread_kill(_Thread, SIGKILL);
sem_destroy(&_TaskCount);
}
int CThreadQueue::AddTask(CThreadTask Task)
{
pthread_mutex_lock(&_Mutex);
_Queue.push_back(TempTask);
sem_post(&_TaskCount)
pthread_mutex_unlock(&_Mutex);
return 0;
}
void *CThreadQueue::StartThread(void *Obj)
{
((CThreadQueue*)Obj)->RunThread();
return NULL;
}
//runs in a separate thread
void CThreadQueue::RunThread()
{
CThreadQueue::CTask Task;
while(1) {
sem_wait(&_TaskCount);
pthread_mutex_lock(&_Mutex);
Task = _Queue.front();
_Queue.pop_front();
pthread_mutex_unlock(&_Mutex);
if (Task.Callee != NULL)
Task.Callee->CallBackFunc(NULL, Task.CallParam);
}
}
解决方案
可能出什么问题了?任何数量的事情。其他原因可能会破坏信号量或覆盖用于存储信号量的内存或指向信号量的指针。另一种可能性是您调用 sem_post() 次数过多,导致计数器溢出。代码示例会有所帮助。
其他提示
我们遇到了同样的问题,经过很长时间弄清楚可能发生的情况后,我们发现问题的发生是因为信号量是在一个结构体中定义的,该结构体的字节对齐更改为 1(在本例中使用 pragma pack(1 )指令)。
Linux 上的 POSIX 信号量实现使用 futex 系统调用。根据 futex 手册页,当“未定义操作或页面对齐错误”时,将返回 EINVAL。
在我们的例子中,要么删除 pragma pack(1) 指令,要么将信号量定义为结构体的第一个元素,就解决了问题。
不隶属于 StackOverflow