Python и FIFO - PullRequest
       33

Python и FIFO

6 голосов
/ 23 февраля 2011

Я пытался понять FIFO, используя Python под Linux, и обнаружил странное поведение, которое я не понимаю.

Ниже приведено fifoserver.py

import sys
import time

def readline(f):
    s = f.readline()
    while s == "":
        time.sleep(0.0001)
        s = f.readline()
    return s

while True:
    f = open(sys.argv[1], "r")
    x = float(readline(f))
    g = open(sys.argv[2], "w")
    g.write(str(x**2) + "\n")
    g.close()
    f.close()
    sys.stdout.write("Processed " + repr(x) + "\n")

, и это fifoclient.py

import sys
import time

def readline(f):
    s = f.readline()
    while s == "":
        time.sleep(0.0001)
        s = f.readline()
    return s

def req(x):
    f = open("input", "w")
    f.write(str(x) + "\n")
    f.flush()
    g = open("output", "r")
    result = float(readline(g))
    g.close()
    f.close()
    return result

for i in range(100000):
    sys.stdout.write("%i, %s\n" % (i, i*i == req(i)))

Я также создал два FIFO, используя mkfifo input и mkfifo output.

Я не понимаю, почему, когда я запускаю сервер (с python fifoserver.py input output)и клиент (с python fifoclient.py) из двух консолей после некоторых запросов клиент вылетает с ошибкой «сломанный канал» в f.flush().Обратите внимание, что перед сбоем я видел от нескольких сотен до нескольких тысяч правильно обработанных запросов, работающих нормально.

В чем проблема в моем коде?

Ответы [ 2 ]

5 голосов
/ 23 февраля 2011

Как уже упоминалось в других комментариях, у вас есть условие гонки.

Я подозреваю, что в случае сбоя сервер приостанавливается после одной из следующих строк:

g.write(str(x**2) + "\n")
g.close()

Затем клиент может прочитать результат, распечатать его на экране и вернуться к началу.Затем он снова открывает f - что успешно, потому что он все еще открыт на стороне сервера - и записывает сообщение.Тем временем серверу удалось закрыть f.Затем очистка на стороне клиента выполняет системный вызов write() на канале, который запускает SIGPIPE, потому что теперь он закрыт с другой стороны.

Если я прав, вы сможете исправить это, переместив f.close() сервера выше g.write(...).

0 голосов
/ 23 февраля 2011

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

Я не понимаю, почему вы все время открываете и закрываете трубу.

Попробуйте запустить процесс, который сначала читает канал, пусть он откроет канал, и он будет сидеть в ожидании данных.

Затем запустите программу записи каналов и попросите ее перекачать все данные, которые вы хотите отправить. Он остановится, если продвинется. Когда писатель закрывает канал, читатель получает нулевые байты вместо блокировки и должен закрыться. IIRC, Python обнаруживает это и возвращает EOF.

...