【问题标题】:sem_post() fail with valid semaphoresem_post() 因有效信号量而失败
【发布时间】:2009-03-26 10:57:46
【问题描述】:

我有一个带有信号量的队列。在某些时候,所有对sem_post() 的调用总是返回“无效参数”错误,尽管信号量本身是有效的

信号量是 C++ 对象的私有成员,永远不会被删除,它也可以在 gdb 中检查。我在sem_post() 之前添加了sem_getvalue() - 该值显示为OK,然后在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);
    }
}

【问题讨论】:

  • 你能生成一个重现问题的测试程序吗?
  • 嗨,杰克,你知道发生了什么吗?谢谢!
  • 对不起,大卫。我无法重现该问题。那是很久以前的事了,从 diff 我生气的唯一一件事就是检查 sem_wait()
  • 像这样: int SemResult = sem_wait(&_TaskCount); if (SemResult != 0) { if (errno != EINTR) //EINTR 正常:可能是 gdb LOG_ERRNO

标签: linux semaphore


【解决方案1】:

可能出了什么问题?任何数量的东西。其他东西可能正在破坏信号量或覆盖用于存储它的内存或指向它的指针。另一种可能性是您调用 sem_post() 太多次并且计数器溢出。代码示例会有所帮助。

【讨论】:

  • 我遇到了同样的问题,我不知道会发生什么。我检查了计数器没有溢出,内存是正确的,但是更奇怪的是sem_post返回-1但是里面的计数器却正确增加了……
【解决方案2】:

我们遇到了同样的问题,经过很长时间弄清楚可能发生的情况后,我们发现问题的发生是因为信号量是在一个字节对齐更改为 1 的结构内定义的(在本例中使用 pragma pack(1) 指令)。

Linux 上的 POSIX 信号量实现使用 futex 系统调用。根据 futex 手册页,当“未定义操作或页面对齐错误”时返回 EINVAL。

在我们的例子中,要么删除 pragma pack(1) 指令,要么将信号量定义为结构的第一个元素,解决了问题。

【讨论】:

  • +1 是一个很好的例子,说明为什么不应使用压缩结构
猜你喜欢
  • 2014-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-12
  • 2019-01-06
  • 2020-05-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多