0

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;
            }

        }
    }
}

上記のコードは技術的な観点からは正常に機能しますが、呼び出された外部プロセスのさまざまなインスタンスの戻り値の処理に問題があります。特に、特定のインスタンスに関連付けられた戻り値が別のインスタンスにランダムに割り当てられることがあります。たとえば、外部プロセスの 4 つの異なるインスタンスがそれぞれ引数 meas1、meas2、meas3、および meas4 で呼び出され、meas1、meas2、および meas3 が正常に処理され、meas4 のプロセスが失敗したとします。このような状況では、私のコードは戻り値を混同して、meas1、meas3、および meas4 の成功と meas2 の失敗、または meas1、meas2、meas4 の成功と meas3 の失敗を示します。

なぜこれが起こるのかについて何か考えはありますか?

どんな助けでも大歓迎です。

ご清聴ありがとうございました。

4

1 に答える 1

3

プロセス内の任意のスレッドが実行されるwait()と、プロセスの停止した子に関する情報が取得されます。必ずしも、待機中のスレッドによって開始された最後の子に関する情報ではありません。

次のことを考える必要があります。

  1. 停止したプロセスの PID を取得します ( によって返されwait()ますが、無視します)。
  2. 「死体のディスポーザー」として指定された単一のスレッド (wait()子プロセスのファミリーの死を記録および報告するだけのスレッド) を持つ。
  3. プロセスを開始するスレッドが、子プロセスが終了したときのステータスに関心があることを記録できるようにするデータ構造。おそらく、子プロセスが起動したら、適切な条件で子プロセスを待機する必要があります。これにより、何も役に立たないために CPU 時間を消費することはありません。
  4. 「死体処理」スレッドは、死体を収集するたびに、適切な他のスレッドの通知を処理します。
  5. プロセスのタイムアウトを心配し、長時間暴走する子供たちを殺します。

時には病的なビジネスです...

于 2012-07-13T14:18:57.307 に答える