记录fork子进程执行execl阻塞卡死的问题

源代码:

static void *cmd_exec_thread_handler(void *arg)
{
    pthread_cleanup_push(thread_exit_handler, arg);

    cmd_base_t *cmd_base = (cmd_base_t *)arg;

    printf("fork process\n");
    fflush(stdout);
    pid_t pid = fork();
    if (pid < 0) {
        perror("fork process error");
        printf("for process error");
        fflush(stdout);
    }
    else if (pid == 0) {
        printf("for clild process ok");
        fflush(stdout);
        cmd_base->pid = getpid();
//        log_debug("----------> start process(pid: %d)\n", cmd_base->pid);
        execlp("bash", "bash", "-c", cmd_base->cmd, NULL);
    }
    else if (pid > 0) {
        cmd_base->pid = pid;
        int status = 0;
        log_info("------------> wait pid (%d)\n", cmd_base->pid);
        waitpid(cmd_base->pid, &status, WUNTRACED); // 等待进程结束
        if (WIFEXITED(status)) {
            log_debug("waitpid process exit OK\n");
        }
        else if (WEXITSTATUS(status)) {
            log_debug("waitpid process exit: %d\n", WEXITSTATUS(status));
        }
        else if (WIFSIGNALED(status)) {
            log_debug("waitpid process exit by signal(%s) of process(pid: %d)\n", sys_siglist[(WTERMSIG(status))], getpid());
        }
        else if (WCOREDUMP(status)) {
            log_debug("waitpid process exit by coredump error\n");
        }
    }

    log_debug("----------> cmd: %s is over (pid: %d)\n", cmd_base->cmd, cmd_base->pid);
    cmd_base->pid = -1;
    cmd_base->run = false;

    pthread_cleanup_pop(1);
    return NULL;
}

上面的函数是一个线程执行函数,调用这个函数,execlp有概率会出现阻塞的情况。
网上翻了一下资料参考链接,造成这个的原因是产生了死锁。

因为我使用了自己的日志库,日志库里面有互斥锁用来保证输入数据的一致性。

在这里插入图片描述
当父进程中的线程有调用日志打印函数时,会对互斥锁上锁,在还未解锁的情况,如果这时刚好fork子进程成功,并在子进程中执行日志打印函数的话,这个时候就会发生上面的所说的情况。

解决方法

  • 方法一: 使用vfork代替fork。子进程不从父进程中继承锁。(此时,没有再出现过问题。但是不推荐使用vfork)
  • 方法二:自己除了调用exec外,不要再干其它事情,比如输出日志。尽量不要有关于锁的操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值