Парные сокеты и ошибка Broken pipe (EPIPE) [РЕШЕНО]

Добрый день!

Пишу программу на С (-std=gnu99). Программа является демоном. Во время работу создаётся дочерний процесс через fork. Этот дочерний процесс работает в бесконечном цикле до тех пор, пока не получит команду на завершение.
Команду он получает через парные сокеты от родительского процесса. Родительский процесс посылает дочернему процессу команду на завершение при получении сигнала SIGUSR2. Но вот тут то и наступает проблема! При записи в сокет появляется сигнал SIGPIPE и write выставляет ошибку EPIPE (Broken pipe). В чём может быть проблема?

Парные сокеты создаются. Ошибок при создании нет.

int control_sockpair[2];
int setsockopt_ret = 0;

socketpair_ret = socketpair(AF_UNIX, SOCK_STREAM, 0, control_sockpair);
if(socketpair_ret < 0){
	log_print("Ошибка при создании парных сокетов\n");
}else{
	log_print("Парный сокет создан успешно\n");
}

Далее закрываю сокет для чтения:

(void) close(control_sockpair[SOCKPAIR_READ]);

Затем ответвляюсь и в дочернем процессе закрываю сокет для записи:

(void) close(control_sockpair[SOCKPAIR_WRITE]);

Константы SOCKPAIR_READ и SOCKPAIR_WRITE:

#define SOCKPAIR_READ 0
#define SOCKPAIR_WRITE 1

Затем в обработчике сигнала SIGUSR2 записываю данные:

int count = 0;
char buf[1024];

memset(buf, 0, 1024);

// Тут формируется строка для посылки

count = write(control_sockpair[SOCKPAIR_WRITE], buf, strlen(buf) + 1);
if(count < 0){
	log_print("Ошибка (код: %d) при отправки данных серверу: %s\n", errno, strerror(errno));
}

В лог выводится строка:
Ошибка (код: 32) при отправки данных серверу: Broken pipe

Есть соображения как поймать ошибку и устранить?

:_:

на вашем месте можно было бы поискать в http://www.google.com/codesearch?as_q=socketpair+fork&as_lang=c разные варианты использования

а эта строка - это просто подпись

Спасибо, но я не просил

Спасибо, но я не просил варианты использования. Я написал как я их использую. И мне нужен мой вариант.
Я спросил, почему может быть ошибка, описанная выше, а именно Broken pipe.

UPD1
Мне нужен системный программист, а не "гуглильщик".

UPD2
Вы вообще что ли не читаете что люди пишут? Года два-год назад форум был супер! На любой вопрос люди отвечали чётко и ясно! Это был лучший форум по теме во всём Интернете! Теперь же уже который раз встречаюсь с тем, что люди отправляют к гуглу, дают ложные советы, пишут ссылки на маны (спасибо, но если бы просили ссылку на ман, так бы и написали!!!), лезут с какой-то, не относящейся к теме, болтавнёй. Такое ощущение что все профессионалы куда исчезли отсюда и остались только любители "потрепаться". Что написано вообще читать перестали! Не понимают люди суть вопроса.
Дорогие друзья-пингвинологи? Куда же вы делись? Толпа "гуглильщиков" скоро, извините, засрут форум бредом и болтавнёй! Давайте спасать положение!

^_^

Не кипятитесь. Я прекрасно помню, каким был форум пару лет назад. Но вас я не помню.
UPD1
Мне нужно, чтобы люди отличали http://www.google.com/codesearch от http://www.google.com

а эта строка - это просто подпись

n0nado написал(а): Не

n0nado написал(а):
Не кипятитесь. Я прекрасно помню, каким был форум пару лет назад. Но вас я не помню.

Давайте не будем вести споры. Я вас тоже не помню. И судя по времени пребывания вашего, пару лет назад вас здесь не было: 14 недель 1 день.
Но, конечно, возможно, что вы сменили логин. Поэтому тоже без претензий. И помнить кого-то вовсе не обязательно. Я не сижу здесь всеми днями и не прошу чтобы меня узнавали постоянно!
Линуксоиды - братья. Так что давайте жить дружно и не ругаться. :)

n0nado написал(а):
UPD1
Мне нужно, чтобы люди отличали http://www.google.com/codesearch от http://www.google.com

Я не просил у вас помощи по работе с гуглом. Вопрос был вполне ясно выражен, а вы ответили вообще непонятно про что.
Я просил помочь с ошибкой, а вы отправили к коду, который не имеет отношения к делу. Я спрашивал про SIGPIPE, а вы ответили вообще не о том. Про какую то реализацию обмена через парные сокеты.
Я же привёл пример и показал как я работаю. И просил найти ошибку. А вы этого не поняли.

Вопрос решён, тема закрыта.

Решено

Добрый день!

В общем, ошибку нашёл сам. Начал с подробного изучения случаев возникновения Broken pipe. На сайте opennet нашёл доку (русский перевод на GNU libc) http://www.opennet.ru/docs/RUS/glibc/glibc-21.html, в которой написано про сигналы. Меня интересует именно сигнал SIGPIPE.
(Вся дока тут: http://www.opennet.ru/docs/RUS/glibc/)

Вот что написано про SIGPIPE:

Цитата:
Если Вы используете водопроводы или FIFO, Вы должны разработать ваше приложение так, чтобы один процесс открыл водопровод для чтения перед тем как другой начал запиись. Если процесс считывания никогда не начинается, или завершается неожиданно, запись в водопровод или FIFO вызывает сигнал SIGPIPE. Если SIGPIPE блокирован, обрабатывается или игнорируется, дргие обращения вызывают EPIPE взамен.

Водопроводы и FIFO обсуждены более подробно в Главе 10 [Водопроводы и FIFO].

Другая причина SIGPIPE - когда Вы пробуете выводить на сокет, который не соединен.

Перевод, конечно, дословный, но не это главное. Главное то, что он натолкнул на мысль! :)

Затем я стал рассматривать свой код и тут до меня дошло!!!
Я сначала создал парный сокет, затем закрыл ненужный мне дескриптор на чтение, затем ответвился и в дочернем процессе закрыл дескриптор на запись.
Так вот, видно же сразу - сначала создал и закрыл один из концов парного сокета, а затем уже ответвился!
Таким образом канал был разорван. В дочернем процессе у меня уже не было дескриптора на чтение, т.к. я закрыл его раньше.

И конечно при вызове write я писал в существующий дескриптор (его существование даже проверил специально вызовом fcntl с флагом F_GETFD), но другой конец парного сокета был закрыт. А наследовать его не успели!

Вот тут то и возникала проблема. Посылался сигнал SIGPIPE и write возвращал -1, а errno выставлялась в EPIPE (Broken pipe).

В общем-то, ошибка, конечно, детская, но сразу так и не найдёшь!

Всем спасибо кто читал и задумывался. :)

Надеюсь, данная тема кому-то поможет в дальнейшем избегать подобного рода ошибок!

Настройки просмотра комментариев

Выберите нужный метод показа комментариев и нажмите "Сохранить установки".