c 中的管道写入和读取错误:程序冻结

如何解决c 中的管道写入和读取错误:程序冻结

我正在通过 fork 运行带有多处理的 c 代码,并使用管道使子进程与父进程通信。

但是在运行 write 部分时,假设 13 个进程中有 3 个成功了,然后程序就被冻结了,这意味着它不能再进一步了,segmentation fault ,无论如何也没有停止。

我无法使用 gdb 进行调试,即使使用 set follow-fork-mode childValgrind,程序也只是被冻结了。

代码如下:

  1. 功能:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <unistd.h>


struct IntArrLen {
 int length;
 int index;
 int* arr;
};

struct IntArrLenArr {
 struct IntArrLen *intArrLen;
 int max_index;
 int length;
};

void write_check(int fd,void *buffer,size_t len){
    char *p = buffer;
    while(len > 0){
        size_t wlen = write(fd,p,len);
        if(wlen <= 0){
            printf("Error when writing.\n");
            exit(0);
        }
        p += wlen;
        len -= wlen;
    }
}

void write_intArrLen(int fd,struct IntArrLen *p){
    write_check(fd,&p->index,sizeof(p->index));
    write_check(fd,&p->length,sizeof(p->length));
    write_check(fd,p->arr,p->length * sizeof(*p->arr));
}


void write_intArrLenArr(int fd,struct IntArrLenArr *p){
    write_check(fd,&p->max_index,sizeof(p->max_index));
    write_check(fd,sizeof(p->length));
    int i;
    for(i=0; i<p->length; i++)
        write_intArrLen(fd,&p->intArrLen[i]);
}


void read_check(int fd,size_t len){
    char *p = buffer;
    while (len > 0){
        size_t rlen = read(fd,len);
        if(rlen <= 0){
            printf("Error when reading.\n");
     
            exit(0);
        }
        p += rlen;
        len -= rlen;
    }
}

void read_intArrLen(int fd,struct IntArrLen *p){
    read_check(fd,sizeof(p->index));
    read_check(fd,sizeof(p->length));
    p->arr = malloc(p->length * sizeof(*p->arr));
    if(!p->arr){
        printf("ran out of memory.\n");
        exit(0);
    }
    read_check(fd,p->length * sizeof(*p->arr));
}

void read_intArrLenArr(int fd,struct IntArrLenArr *p){
    read_check(fd,sizeof(p->max_index));
    read_check(fd,sizeof(p->length));
    p->intArrLen = malloc(p->length * sizeof(*p->intArrLen));
    if(!p->intArrLen){
        printf("ran out of memoty.\n");
        exit(0);
    }
    int i;
    for(i=0; i<p->length; i++)
        read_intArrLen(fd,&p->intArrLen[i]);
}

struct IntArrLenArr getRes(int num1,int num2){
    struct IntArrLenArr ret;
    ret.length = num1;
    ret.max_index = num2;
    ret.intArrLen = malloc(sizeof(struct IntArrLen) * num1);
    int i,j;
    for(i=0; i<num1; i++){
        ret.intArrLen[i].length = num1;
        ret.intArrLen[i].index = num2;
        ret.intArrLen[i].arr = malloc(sizeof(int) * num1);
        for(j=0; j<num2; j++){
            ret.intArrLen[i].arr[j] = j;
        }
    }

    return ret;
}


int main(void){

    struct IntArrLenArr res;
    res.max_index = 0;
    res.length = 0;
    int i;

    pid_t child_pid;
    int *fds = malloc(sizeof(int) * 13 * 2);

    for(i=0; i<13; i++){
        if(pipe(fds + i*2) <0)
            exit(0);
    }

    for(i=0; i<13; i++){
        //fflush(NULL);
        child_pid =fork();
        if(child_pid == 0){
            close(fds[i*2]);
            res = getRes(20,3000000); // 300,000 works but not with 3000,000
            if(res.length != 0){
                printf("-----------%d\n",i);
                write_intArrLenArr(fds[i*2+1],&res);
                printf("+++++++++++%d\n",i);
            }
            close(fds[i*2+1]);
            exit(0);
        }else if(child_pid == -1){
            printf("fork error\n");
            exit(0);
        }
    }

    for(i=0; i<13; i++){
        close(fds[i*2+1]);
        read_intArrLenArr(fds[i*2],&res);
        printf(".................%d\n",i);
        if (res.length > 0){
            printf("do something\n");
       }
    }

    return 1;
}
                                                                                  

res 像这样:

res -> length: 20
    -> max_index: 458965845
    -> IntArrLen: -> IntArrLen[0] -> length: 125465
                                  -> index: 45687987
                                  -> int * arr: 123,1565,48987,45879,... // 125465 numbers
                  -> IntArrLen[1] -> length: 5465798956
                                  -> index: 34579999
                                  -> int * arr: 78123,... // 5465798956 numbers
                  -> IntArrLen[2] -> length: 5465798956
                                  -> ....
                  -> ...

有人能帮我找出这里有什么问题吗?或者有没有其他方法可以以某种方式调试代码?非常感谢!!

解决方法

我从问题中的代码(源文件 pipe53.c 编译为可执行文件 pipe53)中获得了这段代码:

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

struct IntArrLen
{
    int length;
    int index;
    int *arr;
};

struct IntArrLenArr
{
    struct IntArrLen *intArrLen;
    int max_index;
    int length;
};

static size_t bytes_allocated = 0;

struct IntArrLenArr getRes(int num1,int num2);
void read_check(int fd,void *buffer,size_t len);
void read_intArrLen(int fd,struct IntArrLen *p);
void read_intArrLenArr(int fd,struct IntArrLenArr *p);
void write_check(int fd,size_t len);
void write_intArrLen(int fd,struct IntArrLen *p);
void write_intArrLenArr(int fd,struct IntArrLenArr *p);

static void fd_close(int fd)
{
    close(fd);
    //fprintf(stderr,"%d: closing %d\n",(int)getpid(),fd);
}

static void report_memory_used(void)
{
    fprintf(stderr,"%d: bytes allocated = %zu\n",bytes_allocated);
}

static void *memory_allocator(size_t nbytes)
{
    void *vp = malloc(nbytes);
    bytes_allocated += nbytes;
    report_memory_used();       // Dire straights!
    return vp;
}

void write_check(int fd,size_t len)
{
    char *p = buffer;
    fprintf(stderr,"%d: writing %zu bytes to fd %d\n",len,fd);
    while (len > 0)
    {
        ssize_t wlen = write(fd,p,len);
        if (wlen <= 0)
        {
            fprintf(stderr,"%d: Error when writing fd = %d.\n",fd);
            exit(0);
        }
        p += wlen;
        len -= wlen;
    }
}

void write_intArrLen(int fd,struct IntArrLen *p)
{
    write_check(fd,&p->index,sizeof(p->index));
    write_check(fd,&p->length,sizeof(p->length));
    write_check(fd,p->arr,p->length * sizeof(*p->arr));
}

void write_intArrLenArr(int fd,struct IntArrLenArr *p)
{
    write_check(fd,&p->max_index,sizeof(p->max_index));
    write_check(fd,sizeof(p->length));
    for (int i = 0; i < p->length; i++)
        write_intArrLen(fd,&p->intArrLen[i]);
}

void read_check(int fd,size_t len)
{
    char *p = buffer;
    while (len > 0)
    {
        ssize_t rlen = read(fd,len);
        if (rlen < 0)
        {
            fprintf(stderr,"%d: Error %d (%s) when reading fd = %d.\n",errno,strerror(errno),fd);
            exit(0);
        }
        if (rlen == 0)
        {
            fprintf(stderr,"%d: Premature EOF when reading fd = %d.\n",fd);
            break;
        }
        p += rlen;
        len -= rlen;
    }
}

void read_intArrLen(int fd,struct IntArrLen *p)
{
    read_check(fd,sizeof(p->index));
    read_check(fd,sizeof(p->length));
    p->arr = memory_allocator(p->length * sizeof(*p->arr));
    if (!p->arr)
    {
        printf("ran out of memory.\n");
        fprintf(stderr,"%d: ran out of memory (%zu bytes requested)\n",p->length * sizeof(*p->arr));
        exit(EXIT_FAILURE);
    }
    read_check(fd,p->length * sizeof(*p->arr));
}

void read_intArrLenArr(int fd,struct IntArrLenArr *p)
{
    read_check(fd,sizeof(p->max_index));
    read_check(fd,sizeof(p->length));
    p->intArrLen = memory_allocator(p->length * sizeof(*p->intArrLen));
    if (!p->intArrLen)
    {
        fprintf(stderr,p->length * sizeof(*p->intArrLen));
        exit(EXIT_FAILURE);
    }
    for (int i = 0; i < p->length; i++)
        read_intArrLen(fd,&p->intArrLen[i]);
}

struct IntArrLenArr getRes(int num1,int num2)
{
    struct IntArrLenArr ret;
    ret.length = num1;
    ret.max_index = num2;
    ret.intArrLen = memory_allocator(sizeof(struct IntArrLen) * num1);
    if (ret.intArrLen == NULL)
    {
        fprintf(stderr,"%d: failed to allocate %zu bytes of memory\n",sizeof(struct IntArrLen) * num1);
        exit(EXIT_FAILURE);
    }
    for (int i = 0; i < num1; i++)
    {
        ret.intArrLen[i].length = num1;
        ret.intArrLen[i].index = num2;
        ret.intArrLen[i].arr = memory_allocator(sizeof(int) * num1);
        if (ret.intArrLen[i].arr == NULL)
        {
            fprintf(stderr,sizeof(int) * num1);
            exit(EXIT_FAILURE);
        }
        for (int j = 0; j < num2; j++)
        {
            ret.intArrLen[i].arr[j] = j;
        }
    }

    return ret;
}

int main(void)
{
    struct IntArrLenArr res;
    res.max_index = 0;
    res.length = 0;

    atexit(report_memory_used);

    printf("Parent process: %d\n",(int)getpid());

    int *fds = memory_allocator(sizeof(int) * 13 * 2);

    for (int i = 0; i < 13; i++)
    {
        if (pipe(fds + i * 2) < 0)
        {
            fprintf(stderr,"failed to create pipe %d\n",i);
            exit(EXIT_FAILURE);
        }
    }

    for (int i = 0; i < 13; i++)
    {
        pid_t child_pid = fork();
        if (child_pid == 0)
        {
            printf("%d: Child process: %d - pipe [%d,%d]\n",i,fds[i * 2 + 0],fds[i * 2 + 1]);
            for (int j = 0; j < 13; j++)
            {
                fd_close(fds[j * 2 + 0]);
                if (i != j)
                    fd_close(fds[j * 2 + 1]);
            }
            //res = getRes(20,3000000); // 300,000 works but not with 3000,000
            res = getRes(20,300000); // 300,000
            report_memory_used();
            if (res.length != 0)
            {
                printf("-----------%d\n",i);
                write_intArrLenArr(fds[i * 2 + 1],&res);
                printf("+++++++++++%d\n",i);
            }
            fd_close(fds[i * 2 + 1]);
            exit(0);
        }
        else if (child_pid == -1)
        {
            fprintf(stderr,"fork error\n");
            exit(EXIT_FAILURE);
        }
        else
        {
            fprintf(stderr,"%d: launched child %d\n",(int)child_pid);
        }
    }

    for (int i = 0; i < 13; i++)
    {
        fd_close(fds[i * 2 + 1]);
        read_intArrLenArr(fds[i * 2 + 0],&res);
        printf(".................%d\n",i);
        if (res.length > 0)
        {
            printf("do something\n");
        }
        fd_close(fds[i] * 2 + 0);
    }

    free(fds);
    return 0;
}

我从运行它(在 MacBook Pro 上)得到的输出示例是:

$ ./pipe53 2>&1 | cat           # I actually pipe the output to "so | pbcopy" …
23380: bytes allocated = 104
23380: launched child 23383
23380: launched child 23384
23383: bytes allocated = 424
23383: bytes allocated = 504
23380: launched child 23385
23384: bytes allocated = 424
23384: bytes allocated = 504
23380: launched child 23386
23385: bytes allocated = 424
23385: bytes allocated = 504
23380: launched child 23387
23386: bytes allocated = 424
23386: bytes allocated = 504
23380: launched child 23388
23387: bytes allocated = 424
23387: bytes allocated = 504
23388: bytes allocated = 424
23388: bytes allocated = 504
23380: launched child 23389
23380: launched child 23390
23389: bytes allocated = 424
23389: bytes allocated = 504
23380: launched child 23391
23390: bytes allocated = 424
23390: bytes allocated = 504
23380: launched child 23392
23391: bytes allocated = 424
23391: bytes allocated = 504
23380: launched child 23393
23392: bytes allocated = 424
23392: bytes allocated = 504
23380: launched child 23394
23393: bytes allocated = 424
23393: bytes allocated = 504
23380: launched child 23395
23394: bytes allocated = 424
23394: bytes allocated = 504
23380: Premature EOF when reading fd = 3.
23380: Premature EOF when reading fd = 3.
23395: bytes allocated = 424
23395: bytes allocated = 504
23380: bytes allocated = 104
23380: Premature EOF when reading fd = 5.
23380: Premature EOF when reading fd = 5.
23380: bytes allocated = 104
23380: Premature EOF when reading fd = 7.
23380: Premature EOF when reading fd = 7.
23380: bytes allocated = 104
23380: Premature EOF when reading fd = 9.
23380: Premature EOF when reading fd = 9.
23380: bytes allocated = 104
23380: Premature EOF when reading fd = 11.
23380: Premature EOF when reading fd = 11.
23380: bytes allocated = 104
23380: Premature EOF when reading fd = 13.
23380: Premature EOF when reading fd = 13.
23380: bytes allocated = 104
23380: Premature EOF when reading fd = 15.
23380: Premature EOF when reading fd = 15.
23380: bytes allocated = 104
23380: Premature EOF when reading fd = 17.
23380: Premature EOF when reading fd = 17.
23380: bytes allocated = 104
23380: Premature EOF when reading fd = 19.
23380: Premature EOF when reading fd = 19.
23380: bytes allocated = 104
23380: Premature EOF when reading fd = 21.
23380: Premature EOF when reading fd = 21.
23380: bytes allocated = 104
23380: Premature EOF when reading fd = 23.
23380: Premature EOF when reading fd = 23.
23380: bytes allocated = 104
23380: Premature EOF when reading fd = 25.
23380: Premature EOF when reading fd = 25.
23380: bytes allocated = 104
23380: Premature EOF when reading fd = 27.
23380: Premature EOF when reading fd = 27.
23380: bytes allocated = 104
23380: bytes allocated = 104
Parent process: 23380
.................0
.................1
.................2
.................3
.................4
.................5
.................6
.................7
.................8
.................9
.................10
.................11
.................12

AFAICT,getRes() 函数(大小为 300,000 和 3,000,000)不会触发子进程写入的任何内容。

注意在调试消息中小心使用识别 PID。

您需要修改 getRes() 以便将数据写入父进程。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res