c++ - 实现信号量时混淆核心转储

标签 c++ c semaphore

根据: http://www.haiku-os.org/legacy-docs/benewsletter/Issue1-26.html#Engineering1-26

我在 g++ 4.4.6 中实现了以下内容!!

#ifndef BENAPHORE_
#define BENAPHORE_

#include <string>
#include <memory>
#include <utility>
#include <semaphore.h>
#include <pthread.h>
#include <assert.h>

class benaphore
{
private:
    char fname[128] ;
    sem_t* benaphore_sem ;
    int benaphore_atom ;
    bool closed ;
public:
    benaphore()
    {
        benaphore_atom = 0 ;
    }
    ~benaphore()
    {
        if(!closed)
        {
            sem_close(benaphore_sem) ;
            sem_unlink(fname) ;
        }
    }
    void close_benaphore()
    {
        sem_close(benaphore_sem) ;
        sem_unlink(fname) ;
        closed = true ;
    }
    void open_benaphore(char* fname_)
    {
        closed = false ;
        strcpy(fname,fname_) ;
        benaphore_sem = sem_open(fname,O_CREAT,0644,0);
        if(benaphore_sem == SEM_FAILED)
        {
            printf("benaphore sem_open error \n") ;
        }
    }
    void acquire_benaphore()
    {
        int previous_value;
        previous_value = __sync_fetch_and_add(&benaphore_atom, 1);

        if (previous_value > 0)
            sem_wait(benaphore_sem);
    }

    void release_benaphore()
    {
        int previous_value;
        previous_value = __sync_fetch_and_add(&benaphore_atom, -1);

        if (previous_value > 1)
            sem_post(benaphore_sem);
    }
} ;

#endif

和测试源:

#include "benaphore.hpp"

benaphore b1 ;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int glbCnt[6]={0,0,0,0,0,0} ;
void gexit(int gub)
{
    b1.close_benaphore() ;
    for(int idx=0;idx<6;idx++)
        printf("(%d)\n",glbCnt[idx]) ;
    sleep(1) ;
    exit(0) ;
}
void *testx(void *arg)
{
    long ilocal = (long)arg ;
    for(int idx=0;idx<3000000;idx++)
    {
        //pthread_mutex_lock(&mutex);
        b1.acquire_benaphore() ;
        ++glbCnt[ilocal]  ;
        b1.release_benaphore() ;
        //pthread_mutex_unlock(&mutex);
    }
}
int main()
{
    char* fname ;
    fname = (char*) malloc(80) ;
    strcpy(fname,"test_benaphore1") ;
    b1.open_benaphore(fname) ;
    signal(SIGINT, gexit);
    signal(SIGTERM, gexit);

    pthread_t id[6];
    int iCPU[6]={0,1,2,3,4,5} ;
    pthread_create(&id[0],NULL,testx,(void *)(long)iCPU[0] );
    pthread_create(&id[1],NULL,testx,(void *)(long)iCPU[1] );
    pthread_create(&id[2],NULL,testx,(void *)(long)iCPU[2] );
    pthread_create(&id[3],NULL,testx,(void *)(long)iCPU[3] );
    pthread_create(&id[4],NULL,testx,(void *)(long)iCPU[4] );
    pthread_create(&id[5],NULL,testx,(void *)(long)iCPU[5] );

    int i ;
    for(i=0;i<6;++i){
        pthread_join(id[i],NULL);
    }
    b1.close_benaphore() ;
    for(int idx=0;idx<6;idx++)
        printf("(%d)\n",glbCnt[idx]) ;
}

编译:

g++ --std=c++0x test_benaphore.cpp -lpthread -o test_benaphore.exe

如果让每个线程都完成,每次我都能得到我想要的正确答案。但是如果我通过键“control-C”发送一个中断信号,然后 gexit() 函数被执行并且大多数应用程序得到“段错误(核心转储)”,大约中断应用程序 10 次,将得到 9 次核心转储,一次没有打印数量小于 3,000,000 的核心转储。

我不知道为什么会这样,欢迎任何意见和建议。

最佳答案

从异步信号处理程序中可以安全地执行的操作并不多,请参阅 this page 的底部一个列表。请注意 exitprintf 不在上面。您可以通过调用 _exit 来消除段错误。

更好的设计可能是完全避免在信号处理程序中进行任何复杂的处理,而只是设置一个标志...

namespace
{
    volatile sig_atomic_t time_to_quit;
}

void gexit(int gub)
{
    time_to_quit = 1;
}

.. 你的线程不时检查

for(int idx=0; !time_to_quit && idx<3000000;idx++)

现在 main 执行所有危险的清理工作,与成功路径相同。

关于c++ - 实现信号量时混淆核心转储,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20490058/

相关文章:

c - 在 Linux 中实现零页的最快方法

ruby-on-rails - 如何让 redis-semaphore 队列 "task_3"直到 "task_1"和 "task_2"已解锁(rails)?

python asyncio - 运行时错误 : await wasn't used with future

c++ - 如何使用 std::is_same 生成编译时错误?

c++ - 计算数组中位置的巧妙方法 (C++)

C++从文件填充结构数组

ios - 从 C api 接收多维数组,如何在 Swift 中处理?

c++ - 0 C++ 内置类型的初始化

c - 预期的声明说明符或 '...' token 之前的 '('?

c - sem_wait 在基本代码中不起作用