Thread: Problem in using execl and pthread

  1. #1
    Registered User
    Join Date
    Nov 2009
    Posts
    6

    Problem in using execl and pthread

    I'm having a problem in the combined use of execl() and pthread.

    My idea is quite simple: write a daemon that in certain situation starts an external process (a separate executable with respect to the daemon itself) and wait for the return value of that process. Moreover I want to have the possibility to start multiple instances of the same process at the same time.

    The part of my code to handle multiple threads:

    Code:
    ...
    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;
            }
    ...
    And the function Start_Process_Thread:

    Code:
    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;
                }
    
            }
        }
    }
    The above code works fine from technical point of view but I have a problem somewhere in handling the return values of the different instances of the called external process. In particular it happens that the return value associated to a certain instance is attributed to a different one randomly.
    For example suppose 4 different instances of the external process are called with the arguments meas1, meas2, meas3 and meas4 respectively and suppose that meas1, meas2 and meas3 are successfully processed and that for meas4 the process fails. In situation like that my code mix up the return vales giving success for meas1, meas3, and meas4 and failure for meas2 or success for meas1, meas2, meas4 and failure for meas3.

    Any idea on why this can happens?

    Any help is really welcome.

    Thank you in advance for your attention.

  2. #2
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    wait() waits on any child. waitpid() is more specific. Check the return value for functions that can fail.
    pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html

    gg

  3. #3
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    778
    I think the wait system call will wait for any child process, not just a child process of that thread, so all threads will try to get the status of any one of the processes. You'll want to use the waitpid system call instead: waitpid(2): wait for process to change state - Linux man page

  4. #4
    Registered User
    Join Date
    Nov 2009
    Posts
    6
    Many thanks to both of you to be so quick in figuring out where the problem was! I have fixed it just changing in my code the line

    Code:
    wait(&status);
    with

    Code:
    waitpid(pid,&status,0);

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problem with execl() and redirection.
    By arunj in forum C Programming
    Replies: 6
    Last Post: 03-20-2008, 08:59 PM
  2. Problem with system(), execl(), etc. functions
    By nickkrym in forum C Programming
    Replies: 5
    Last Post: 05-12-2007, 08:04 AM
  3. pthread producer consumer problem
    By Amit Chikorde in forum C Programming
    Replies: 1
    Last Post: 01-17-2007, 07:39 PM
  4. pthread problem 2
    By rotis23 in forum C Programming
    Replies: 1
    Last Post: 08-20-2002, 05:20 AM
  5. pthread problem
    By rotis23 in forum C Programming
    Replies: 1
    Last Post: 08-17-2002, 08:19 AM