pthread_create中错误 4 的隔离错误

Segfault with error 4 in pthread_create

本文关键字:错误 隔离 create pthread      更新时间:2023-10-16

我一直收到以下带有错误 4 的段错误(通过检查 https://rgeissert.blogspot.com/p/segmentation-fault-error.html 将其 afaik 作为空指针取消引用(:

Aug  6 11:42:54 mypc kernel: [28532305.723536] myapp-new[14784]: segfault at 18 ip 00007f642c6c5d44 sp 00007ffc6a937700 error 4 in libpthread-2.23.so[7f642c6bc000+18000]

代码如下:

void* request(void* p){
    // ... code
}
void Daemon::run(){
    pthread_attr_t attr; 
    pthread_attr_init(&attr); 
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    LOG(INFO) << "daemon running...";
    int sockfd = serverSocket.getSocket();
    struct pollfd fds[1]; 
    fds[0].fd = sockfd; 
    fds[0].events = POLLIN | POLLPRI;
    pthread_t threads[1];
    while (!shutdown_daemon) {
        int currNrThreads = activeThreads;
        int i = 0;
        for (; activeThreads > nrThreads; i++) {
            usleep(4000);
        }
        if (i != 0) {
            LOG(INFO) << "too many threads, slept for " << i * 4 << "ms (" << currNrThreads
                      << " threads, now " << activeThreads << ")";
        }
        // wait until there is data to read on the listen socket
        //
        int retVal = poll(fds, 1, 2000);
        if (retVal == -1) {
            LOG(WARNING) << "error in poll: " << strerror(errno);
        }
        if (retVal <= 0) {
            continue;
        }
        // open a socket to communicate with and read the header
        //
        struct sockaddr_storage clientAddr;
        unsigned int clientLen = sizeof(clientAddr);
        int connectionID = accept(sockfd, (struct sockaddr*)&clientAddr, &clientLen);
        if (connectionID == -1) {
            LOG(WARNING) << "accept return -1, error: " << strerror(errno);
            continue;
        }
        // pack the payload into buffer
        auto buf = new size_t[2];
        buf[0] = (size_t)this;
        buf[1] = (size_t)connectionID;
        int ret = pthread_create(&threads[0], &attr, &request, (void*)buf);
        if (ret != 0) {
            LOG(ERROR) << "could not start pthread, ret: '" << ret << "'";
            delete[] buf;
            continue;
        }
        // Atomic increment
        ++activeThreads; 
    }
    LOG(INFO) << "term signal received, waiting child processess to finish";
    while (activeThreads > 0) {
        LOG(INFO) << "waiting for child processes to finish...";
        sleep(1); }
    LOG(INFO) << "all child processes are finished";
}

具有以下回溯:

(gdb) bt
#0  __pthread_create_2_1 (newthread=<optimized out>, attr=<optimized out>, start_routine=<optimized out>, arg=<optimized out>) at pthread_create.c:713
#1  0x00000000004621fb in Daemon::run (this=0x7ffe1715d260) at src/daemon/daemon.cpp:992
#2  0x0000000000443842 in main (argc=4, argv=0x7ffe1715d6f8) at src/myapp.cpp:991
(gdb) bt full
#0  __pthread_create_2_1 (newthread=<optimized out>, attr=<optimized out>, start_routine=<optimized out>, arg=<optimized out>) at pthread_create.c:713
        stackaddr = <optimized out>
        iattr = <optimized out>
        default_attr = {schedparam = {__sched_priority = 0}, schedpolicy = 0, flags = -1456592096, guardsize = 16,
          stackaddr = 0x409d50 <_GLOBAL__sub_I__ZN4YAML5RegExC2Ev+16>, stacksize = 140729285727984, cpuset = 0x0, cpusetsize = 0}
        free_cpuset = <optimized out>
        pd = 0x7fb373fff700
        retval = <optimized out>
        self = <optimized out>
        thread_ran = true
        __PRETTY_FUNCTION__ = "__pthread_create_2_1"
#1  0x00000000004621fb in Daemon::run (this=0x7ffe1715d260) at src/daemon/daemon.cpp:992
        currNrThreads = -1447528544
        i = 8
        retVal = 0
        clientAddr = {ss_family = 2,
          __ss_padding = "336L177000001", '00' <repeats 24 times>, "260315252737617700000600000000000000daemon0000b3172527376177000032031525273761770000n00000000000000BackupLock002737617700000031625273761770000!303@0000000000274204O00000000", __ss_align = 140729285725960}
        buf = 0x7fb300000000
        clientLen = 32691
        connectionID = 3
        attr = {__size = "000000000000000001000000000000000020", '00' <repeats 37 times>, __align = 0}
        __PRETTY_FUNCTION__ = "void Daemon::run()"
        sockfd = 16
        fds = {{fd = 3, events = 3, revents = 1}}
        threads = {140408722028288}

怎么可能?我会理解一些内存不足错误,但是错误 4 可能发生在此代码中的位置(Ubuntu 16.04, glibc 2.2.3 (

我们还怀疑硬件问题,因此更换了这台机器上的所有RAM,但问题仍然存在。

更新:将软件移动到另一台机器(使用 glibc 2.26(后,崩溃完全停止(在相同的负载下(。

首先,

我会尝试替换以下内容:

// pack the payload into buffer
auto buf = new size_t[2];
buf[0] = (size_t)this;
buf[1] = (size_t)connectionID;

有一个很好的结构,比如:

struct thread_param
{
  Daemon* deamon;
  int connectionID;
}

也许我只是偏执狂,但我不会在以后需要我投射的情况下使用自动声明......

第二

粉碎的理由可能有很多,而你没有提供全部信息。

您的程序是否在以下位置崩溃:

  1. 第一次迭代?
  2. 第二次迭代?
  3. 第 1000 次迭代?

对于每种情况,它可能由其他原因引起:

  1. 您正在使用未初始化的指针。
  2. 您正在使用已删除的指针。
  3. 您有内存泄漏,它会导致某些内存分配失败。例如,如果pthread_create成功,我没有看到您正在删除 buf(我想它应该在 request 函数中,并且您没有检查分配是否已成功......