Моно зависает при попытке открыть 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.