Моно зависает при попытке открыть StreamWriter для именованного канала

Программа, которую я пишу, использует каналы FIFO в linux для межпроцессного общения. В лучшем случае он довольно взломан, но независимо от того, у меня проблемы.

        if (!File.Exists(Path.GetTempPath() + "gminput.pipe"))
        {
            ProcessStartInfo startInfo = new ProcessStartInfo() { FileName = "/usr/bin/mkfifo", Arguments = Path.GetTempPath() + "gminput.pipe", };
            Process proc = new Process() { StartInfo = startInfo, };
            proc.Start();
            proc.WaitForExit();
        }
        if (!File.Exists(Path.GetTempPath() + "gmoutput.pipe"))
        {
            ProcessStartInfo startInfo = new ProcessStartInfo() { FileName = "/usr/bin/mkfifo", Arguments = Path.GetTempPath() + "gmoutput.pipe", };
            Process proc = new Process() { StartInfo = startInfo, };
            proc.Start();
            proc.WaitForExit();
        }

        using (StreamWriter outputPipe = new StreamWriter(Path.GetTempPath() + "gmoutput.pipe"))
        using (StreamReader inputPipe = new StreamReader(Path.GetTempPath() + "gminput.pipe"))
        {
            Console.WriteLine("This code is never reached!");
        }

Все, что я делаю, это проверить, существует ли уже существующий канал, а если нет, вызовите mkfifo для его создания. Эта часть, похоже, работает нормально, именованные каналы создаются правильно. Всякий раз, когда я пытаюсь их открыть (с StreamWriter, StreamReader или с обоими), программа просто зависает. Ошибок нет. Он также зависает в отладчике.

Лучшая часть - это... она работала. У меня было взаимодействие между процессами, и тогда это просто необъяснимо остановилось. Я прокомментировал все, кроме того, что вы видите здесь, перезапустил мою систему, воссоздал трубы и т.д., Но безрезультатно. Что дает? Что-то не так с моим кодом или что-то еще в системе мешает?

Ответ 1

Это по дизайну. Попробуйте следующее: откройте 2 bash терминалы, создайте канал, затем прочитайте его на одном из терминалов и напишите ему в другом. Например

>mkfifo test.fifo
>echo "test" > test.fifo

>cat test.fifo

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

Входная труба процесса 1 представляет собой выходной канал процесса 2 и наоборот. Если оба процесса используют один и тот же код для доступа к трубе, процесс 1 считывает его входной канал и блоки, ожидающие процесса 2, чтобы что-то написать. Процесс 2 также считывает входную трубку и ожидает обработки процесса 1, но процесс 1 ожидает и еще не открыл другой канал. Затор.

Один из способов обойти это - запустить читателя или автора в отдельном потоке. Таким образом, процесс 1 и 2 открывает как трубы, так и тупик.

Другой вариант - открыть асинхронный канал. Мой С# ржавый, но примеров stackoverflow есть много:

Как сделать нежданную запись в именованном канале (С#)?

NamedPipeServerStream в моно

В основном передайте NamedPipeServerStream для чтения/записи.

Я подозреваю, что это сработало до того, как P1 открыл Reader, а затем Writer, а P2 открыл Writer, затем Reader таким образом разблокировал P1.