2014-10-17 65 views
0

我看到一个奇怪的问题。主进程 - > pthread - > fork + execvp

有时当我运行我的程序足够长的时间时,我发现有两个程序正在运行。第二个是第一个子进程,因为我看到第二个进程的父PID是第一个进程的PID。

我意识到我在我的代码中有一个分支,它的唯一原因是我可以有两个副本运行 - 否则我可能永远不会有两个我的程序运行副本。

这种情况很少发生,但确实发生。

架构如下:

主程序获取一个事件,并产生一个并行线程。在那个线程中,我做了一些处理,并根据一些结果,我做了一个fork,紧接着一个execvp。

我意识到它不是最好从pthread调用一个fork,但在我的设计中主进程获得许多事件,并行处理所有这些事件的唯一方法是使用pthread。每个pthread都会进行一些处理,并且在某些情况下需要调用一个不同的程序(为此我使用execvp)。因为我不得不调用一个不同的程序我不得不使用fork

我想知道是否因为我最终从线程上下文调用了一个fork,有可能多个线程并行地调用fork + execvp,并且这个“以某种方式”导致两个副本正在创建。

如果确实发生了这种情况,如果我保护用互斥锁执行fork + execvp的代码,将会有所帮助,因为这会导致只有一个调用fork + execvp的线程。

但是,如果我在fork + excvp之前采取互斥锁,那么我不知道何时释放它。

任何帮助在这里将不胜感激。

线程代码,不会叉+ execvp - 的情况下,你们可以发现有一个问题:

main.c中

status = pthread_create(&worker_thread, tattr, 
           do_some_useful_work, some_pointer); 

[剪裁]

void *do_some_useful_work (void * arg) 
    { 
      /* Do some processing and fill pArguments array */ 

      child_pid = fork(); 

      if (child_pid == 0) 
      { 
       char *temp_log_file; 

       temp_log_file = (void *) malloc (strlen(FORK_LOG_FILE_LOCATION) + 
             strlen("/logfile.") + 8); 

       sprintf (temp_log_file, "%s/logfile.%d%c", FORK_LOG_FILE_LOCATION, getpid(),'\0'); 

       /* Open log file */ 
       int log = creat(temp_log_file, 0777); 
       /* Redirect stdout to log file */ 
       close(1); 
       dup(log); 
       /* Redirect stderr to log file */ 
       close(2); 
       dup(log); 

       syslog(LOG_ERR, "Opening up log file %s\n", temp_log_file); 

       free (temp_log_file); 

       close (server_sockets_that_parent_is_listening_on); 

       execvp ("jazzy_program", pArguments); 

     } 

     pthread_exit (NULL); 

     return NULL; 
    } 

我看着通过这段代码,我看不出为什么我会做一个fork而不是执行一个execvp - 所以我想到的唯一情况是多线程得到执行,并且他们都调用fork + execvp。这有时会导致我的主程序的两个副本运行。

+0

您提供的代码不足以诊断或重现您所问的问题,但我已回答了一些想法。 – 2014-10-17 04:24:14

回答

1

如果execvp因任何原因(可能太多进程,内存不足等)失败,则无法处理该错误;而是线程的分叉副本继续运行。在这个过程中调用pthread_exit(或任何非异步信号安全)函数具有未定义的行为,因此它可能无法正常退出,但会挂起或做出意想不到的事情。您应该始终检查exec失败,并立即_exit(1)或类似的情况发生。另外,虽然这可能不是你的问题,但在多线程进程中分叉之后调用malloc是不安全的,因为它是非异步信号安全的。