printf перестает очищать буфер после execvp в дочернем процессе - PullRequest
0 голосов
/ 06 мая 2020

Теперь я знаю, что эта проблема довольно распространена, но поверьте мне, я не знаю, почему происходит именно этот случай. ребенок. Я использую dup2 в child1, чтобы дублировать стандартный вывод с файлом logfile. Я ожидаю, что оба ребенка будут записывать все сообщения в этот файл.

Вот псевдокод моего приложения.

fork();
if(child1){
  // child 1 operations
  int log_fd = open(logfile, O_CREAT | O_APPEND | O_WRONLY, S_IRUSR | S_IWUSR);
  dup2(log_fd, 1);
  fork();
  if(child2){
    // child 2 operations
    execvp(executable, params);
  }
  else {
    int status;
    wait(&status);
    // child 1 more operations
  }
}
else{
  // parent operations
}

return 0;

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

Вот тестовая программа для executable, которая запускается execvp.

#include <iostream>
#include <unistd.h>

int main(int argc, char const *argv[]) {
  // setvbuf(stdout, NULL, _IONBF, 0);
  printf("pf: started test process\n");
  // std::cout << "co: started test process" << std::endl;
  uint32_t timer = 1;

  while(true){
    // std::cout << "co: tick tick " << timer++ << std::endl;
    printf("pf: tick tick %u\n", timer++);
    // fflush(stdout);
    sleep(1);
  }

  return 0;
}

Проблема в том, что ни один из операторов printf не появляется в logfile . Однако, как вы можете видеть комментируемые операторы, такие как 'cout', 'fflu sh' или 'setvbuf', сообщения печати начинают появляться в logfile. Я не понимаю, почему операторы printf не сбрасывают буфер.

Еще меня беспокоит то, что операторы printf в child 1 operations и child 2 operations в моем псевдокоде приложения работают нормально. Только программа, запущенная execvp, вызывает проблемы. Но почему?!


Дополнительная информация

Это была тестовая программа, которую я написал, чтобы проверить, будет ли мой logi c работать перед фактической разработкой приложения.

#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>

int main(int argc, char const *argv[]){
  const char* name = "/Users/molecule/tp/cpp/output.log";
  char *const args[] = {"ls", NULL};
  int status;

  printf("start\n");

  if (fork() == 0){
    printf("child\n");
    int fd = open(name, O_CREAT | O_APPEND | O_WRONLY, S_IRUSR | S_IWUSR);

    printf("fd %d\n", fd);
    dup2(fd, 1);
    printf("child after dup2\n");

    if(fork() == 0){
      printf("child2\n");
      execvp(args[0], args);
      close(fd);
      exit(0);
    }
  }
  else {
    wait(&status);
    printf("status %d\n", status);
  }

  return 0;
}

Это работает отлично. Результат ls можно увидеть в файле output.log. Но я не могу понять, что не так в моем приложении. Пожалуйста, помогите мне в этот мучительный момент.

...