Программа зависает при использовании процессов

#python #c #fork

#python #c #форк

Вопрос:

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

Мой c-код:

 int main(void) {
    int pid;
    FILE * fp;
    char *calledPython="./a.py"; 
    char *pythonArgs[]={"python",calledPython,"a","b","c",NULL};
    FILE * fp2;
    char str[40];
    pid = fork();

    if(pid == 0) {
        mkfifo("./test",0666);
        fp = fopen("./test","w");
        fprintf(fp,"Hellon");
        fprintf(fp,"Worldn");
    }
    else {
        execvp("python",pythonArgs);
        // if we get here it misfired
        perror("Python execution");
        kill(pid,SIGKILL);
    }

    fp2 = fopen("./test2","r");
    if(fp2 == NULL) {
        printf("NUlln");
    }

    else {
        fscanf(fp2, "%s", str);
        printf("received from test2 %sn", str);
   }
   fclose(fp);
    return 0;
}
  

Мой код на python:

 #!/usr/bin/python


import os, sys

with open("./test") as fp:
    for line in fp:
        print line


path = "./test2"
os.mkfifo(path)

fifo = open(path,"w")
fifo.write("Message from the sendern")
fifo.close()
  

Где ./test — это начальный именованный канал, в который python считывает, а ./test2 — это второй именованный канал, в который c отправляется для чтения.
Однако моя программа зависает, как только я записываю в свой второй канал на python:

 path = "./test2"
os.mkfifo(path)

fifo = open(path,"w")
fifo.write("Message from the sendern")
fifo.close()
  

Вывод, который я получаю от терминала:

 NUll
Hello

World
  

если я запускаю ее снова, я просто получаю пустую строку (вообще ничего не печатается).
Я попытался открыть второй именованный канал в родительском процессе, который, похоже, не сильно изменился. Я не уверен, где я ошибся, есть идеи?

Комментарии:

1. Похоже, что он полон условий гонки.

Ответ №1:

В настоящее время у меня нет под рукой unix-блока для тестирования. Но вероятная проблема заключается в том, что вы не закрываете fifo в родительском процессе.

Всякий раз, когда у вас есть подобный цикл for line in file , этот цикл будет продолжаться до тех пор, пока файл не закончится. В отличие от обычного файла, файл fifo не «завершается», пока процесс на стороне записи не закроет файл fifo. Если вы не закроете fifo, процесс чтения заблокируется при вызове read и не сможет развиваться.

В вашем коде могут быть другие проблемы, которые я упускаю.

Некоторые другие примечания:

  • Вы должны выполнить mkfifo перед выполнением execvp, в настоящее время вы выполняете их параллельно и надеетесь, что mkfifo завершится до того, как ваша программа python попытается открыть файл. Вероятно, но не наверняка.

  • Во втором fifo есть еще одно условие гонки, которое, я думаю, вряд ли будет работать так, как задумано.

  • Вы никогда не удаляете именованный канал, в следующий раз он попытается создать уже существующий файл, который не будет работать.

  • SIGKILL редко является правильным сигналом для использования. Я рекомендую вам ознакомиться с разницей между SIGKILL, SIGTERM и т. Д.

  • Системные вызовы, такие как mkfifo, могут завершиться неудачно, и рекомендуется проверять возвращаемое значение на наличие ошибок.