mysql master线程 fork_多线程中fork的坑

多线程中fork的坑

问题所在

在写oj的时候,由于使用了线程池,并且在获取用户程序运行结果的时候使用的是管道进行子进程的标准输出的获取,

最后带来了一个问题,就是发现本来线程池有5个任务,最后调试信息的打印确没有5个,而且个数不确定。

初步怀疑

是不是线程池出现了死锁的情况。

添加线程池任务

void addTask(clTask* newTask)

{

pthread_mutex_lock(&pthreadMutex);

allTask.push(newTask);

pthread_mutex_unlock(&pthreadMutex);

pthread_cond_broadcast(&pthreadCond);

}

线程主函数

void* clPthread::pthreadMain(void *arg)

{

clPthread& self = *(clPthread*)arg;

while(1)

{

pthread_mutex_lock(&(self.pthreadMutex));

while(0 == self.allTask.size())

{

//阻塞在条件变量上并且解锁互斥锁

pthread_cond_wait(&(self.pthreadCond),&(self.pthreadMutex));

//条件变量满足后,加锁

}

clTask* dealTask = self.allTask.front();

self.allTask.pop();

self.dealTask.push(dealTask);

pthread_mutex_unlock(&(self.pthreadMutex));

dealTask->run();

}

}

这是很标准的的生产者消费者模型了,应该不会出现死锁的情况。但还是怀疑,所以后来我在每次线程池运行的任务的地方打印调试信息,

发现任务是都执行了的,并且是5次,并没有出现死锁的情况。那么问题可能出现在下面的代码中了。

找到问题

再往下面走就是编译和运行的函数了,oj的编译和运行我是采用fork进程然后重定向子进程的标准输出来获取用户程序的编译错误信息和

运行情况的,获取子进程状态和回收子进程使用的是wait函数,至于为什么使用wait函数,因为我的想法是让父进程阻塞等待子进程的编译和运行情况。

问题就出现在这里

由于我是在线程中fork的子进程,子进程结束的时候会触发wait函数

但是此时的wait函数的触发其实不一定是之前的线程fork的子进程触发的,可能是其他线程fork的子进程,因为所有线程fork的子进程的ppid都一样

等于是所有的子进程结束都会使得wait苏醒,但是这个wait确不是应该苏醒的那一个。

void clCompiler::compile()

{

int fd[2];

int ret = pipe(fd);

int res;

pid_t pid;

chdir(workDir.c_str());

solution->prepareCode();

pid = fork();

if(pid > 0){

char buf[1024];

close(fd[1]);

//问题所在的地方

wait(&res);

read(fd[0],buf,sizeof(buf));

close(fd[0]);

if(res == 0){

//编译成功

this->status = COMPLIE_OK;

} else{

//编译失败

this->status = COMPLIE_ERROR;

}

this->complieError = buf;

}else {

//查看ppid都是同一个

printf("ppid:%d\n",getppid());

close(fd[0]);

dup2(fd[1], STDOUT_FILENO);

dup2(fd[1], STDERR_FILENO);

this->doCompile();

close(fd[1]);

exit(0);

}

}

如何解决

既然找到问题了,那么解决也不是很难了,只需要使用函数waitpid指定要回收的进程id就行。

虽然修改一个bug很简单,但是发现问题所在才是需要耐心和能力的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值