2012-07-13 17 views
0

我在execl()和pthread的組合使用中遇到問題。我的想法很簡單:編寫一個守護進程,在某些情況下啓動一個外部進程(關於守護進程本身的一個單獨的可執行文件)並等待該進程的返回值。此外,我想有可能同時啓動同一進程的多個實例。C編程。使用execl和pthread

我的代碼來處理多個線程的部分:

... 
for (c_thread=0,i=0;i<N;i++) 
     { 
     /* Start actions before start threads */ 
     for (j=c_thread;j<c_thread+config.max_threads;j++) 
         Before_Process(act[act_index[j]].measID); 

     /* Now create threads */ 
     for (c=0,j=c_thread;j<c_thread+config.max_threads;j++) 
       { 
         Print_Log(LOG_DEBUG,"Create tread n. %d, measurementID=%s",c,act[act_index[j]].measID); 
         if ((ret=pthread_create(&pth[c],NULL,Start_Process_Thread,(void *) &act[act_index[j]].measID))) 
           { 
             Print_Log(LOG_ERR,"Error in creating thread (errorcode: %d)",ret); 
             exit(EXIT_FAILURE); 
           } 
       c++; 
       } 
     /* Joint threads */ 
     for (j=0;j<config.max_threads;j++) 
       { 
         if ((ret=pthread_join(pth[j], (void**) &r_value[j]))) 
         { 
           Print_Log(LOG_ERR,"Error in joint thread (errorcode: %d)",ret); 
           exit(EXIT_FAILURE); 
         } 
       } 
     /* Perform actions after the thread */ 
     for (j=0;j<config.max_threads;j++) 
       { 
         status=*(int*) r_value[j]; 
         Print_Log(LOG_DEBUG,"Joint tread n. %d. Return value=%d",j,status); 
         After_Process(act[act_index[c_thread+j]].measID,status); 

       } 

     c_thread += config.max_threads; 
     } 
... 

而且功能Start_Process_Thread:

void *Start_Process_Thread(void *arg) 
{ 

int *ret; 
char *measID; 
measID=(char*)arg; 

if (!(ret=malloc(sizeof(int)))) 
     { 
     Print_Log(LOG_ERR, "allocation memory failed, code=%d (%s)", 
           errno, strerror(errno)); 
         exit(EXIT_FAILURE); 
     } 

*ret=Start_Process(measID); 
pthread_exit(ret); 
} 


int Start_Process(char *measID) 
{ 
... 
    pipe(pfd); 
    pid=fork(); 
    if (!pid) 
    { 
     signal(SIGALRM,Timeout); 
     alarm(config.timeout_process); 
     flag=0; 
     /* 
     Start the Process. 
     */ 
      ret=execl(config.pre_processor,buff_list[TokCount-1],config.db_name,measID,(char *) 0); 
     if (ret==-1) 
     { 
      alarm(0); 
      flag=1; 
      Print_Log(LOG_ERR,"Cannot run script %s, code=%d (%s)",config.process, errno, strerror(errno)); 
     } 
     alarm(0); 
     close(1); 
     close(pfd[0]); 
     dup2(pfd[1],1); 
     write(1,&flag,sizeof(int)); 
    } 
    else 
    { 
     wait(&status); 
     close(pfd[1]); 
     read(pfd[0],&flag,sizeof(int)); 
     close(pfd[0]); 
     if (!flag) 
     { 
      if (WIFEXITED(status)) 
      { 
       if (!(return_value=WEXITSTATUS(status))) 
       { 
        /* 
        Process gives no errors. 
        */ 
        Print_Log(LOG_INFO, "Processing of measurementID=%s ended succesfully!",measID); 
       } 
       else 
       { 
        /* 
        Process gives errors. 
        */ 
        Print_Log(LOG_WARNING,"Processor failed for measurementID=%s, code=%d",measID, return_value); 
       } 
      } 
      else 
      { 
       /* 
       Timeout for Process 
       */ 
       Print_Log(LOG_WARNING,"Timeout occurred in processing measurementID=%s",measID); 
       return_value=255; 
      } 

     } 
    } 
} 

上面的代碼工作,從技術上看不錯,但我在某處有問題處理被調用外部進程的不同實例的返回值。特別是它發生的情況是,與某個實例相關的返回值隨機地歸因於一個不同的實例。 例如,假設分別以參數meas1,meas2,meas3和meas4調用外部過程的4個不同實例,並假定meas1,meas2和meas3已成功處理,而meas4過程失敗。在這樣的情況下,我的代碼混淆了返回值,使meas1,meas3和meas4成功,meas2失敗或者meas1,meas2,meas4和meas3失敗成功。

任何想法爲什麼會發生這種情況?

任何幫助真的很受歡迎。

非常感謝您的關注。

回答

3

當進程中的任何線程執行wait()時,它會獲得有關進程的任何死亡子進程—的信息,而不一定是關於正在等待的線程啓動的最後一個子進程。

你將需要思考的問題:

  1. 捕捉死亡(它是由wait()返回,但你忽略)進程的PID。
  2. 有一個單獨的線程被指定爲'屍體處置者'(除了wait()並且記錄和報告子進程中的死亡事件的線程)。
  3. 一個數據結構,它允許啓動進程的線程在它死亡時記錄他們對子狀態感興趣。據推測,一旦孩子開始使用,孩子應該在適當的條件下等待,這樣它就不會耗費CPU時間,無用功。
  4. 「屍體處置者」線程在收集屍體時處理相應其他線程的通知。
  5. 擔心流程超時,以及殺死狂野時間過長的孩子。

這是一個有時病態業務...

+0

謝謝!我已經使用waitpid()函數而不是wait()來解決問題。 – gda 2012-07-13 15:58:29