2014-10-17 3 views
0

У меня странная проблема.основной процесс -> pthread -> fork + execvp

Иногда, когда я запускаю свою программу достаточно долго, я вижу, что есть две копии моей программы. Второй - дочерний процесс первого, так как я вижу, что родительский PID второй - это первый из них.

Я понял, что у меня есть вилка в моем коде, и только из-за этого у меня могут быть две копии - у меня никогда не может быть двух копий моей программы.

Это происходит очень редко, но это происходит.

архитектура выглядит следующим образом:

Основная программа получает событие и порождает PTHREAD. В этом потоке я делаю некоторую обработку и основываясь на некотором результате, я делаю вилку, за которой сразу следует execvp.

Я понимаю, что его не лучше назвать вилкой из pthread, но в моем дизайне основной процесс получает много событий, и единственным способом параллельной работы над всеми этими событиями было использование pthreads. Каждый pthread выполняет некоторую обработку, и в некоторых случаях ему нужно вызвать другую программу (для которой я использую execvp). Так как я должен был вызвать другую программу, мне пришлось использовать 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; 
    } 

Я смотрел через этот код, и я не вижу причин, почему я буду делать вилку, а не execvp, поэтому единственный сценарий, который приходит мне на ум, заключается в том, что несколько потоков выполняются, и все они вызывают fork + execvp. Это иногда приводит к запуску двух копий моей основной программы.

+0

Код, который вы предоставили, недостаточен для диагностики или воспроизведения проблемы, о которой вы просите, но я ответил некоторыми идеями. –

ответ

1

В случае, если execvp не работает по какой-либо причине (возможно, слишком много процессов, из памяти и т. Д.), Вы не справитесь с ошибкой; вместо этого разворачивается копия потока. Вызов pthread_exit (или любая несинхронизированная в сигнале) функция в этом процессе имеет неопределенное поведение, поэтому он может не выйти должным образом, но повесить или сделать что-то неожиданное. Вы всегда должны проверить на ошибку exec и сразу _exit(1) или аналогичный, когда это произойдет. Кроме того, хотя это, вероятно, не ваша проблема, небезопасно вызывать malloc после разветвления в многопоточном процессе, поскольку он не является безопасным для асинхронного сигнала.

Смежные вопросы