LINUX.ORG.RU

[СИ] Убойный SIGPIPE.

 


0

1

[СИ] Убойный SIGPIPE.

Язык СИ
ОС UNIX

Опасна ли такая конструкция (код урезан, но главное осталось):


int get()

{
    signal(SIGPIPE, SIG_IGN);
    
    sd=make_sd();   //--- создает приконнекченный  TCP-сокет ---
    k=write(sd);
    if(k < 0) goto RET;
    k=read(sd);

RET:
    close(sd);
    signal(SIGPIPE, SIG_DFL);
    return();
}

Руководитель потребовал, чтобы при возврате из функции
установить исходную, т. е. дефолтную реакцию на SIGPIPE.
Но при этом должны действовать какие-нибудь другие SIGPIPE,
но только не тот, который от этого сокета.

Опасно ли?
Первое, что приходит в голову - да, опасно.
Сигнал распространяется не мгновенно, и придет после
установки SIG_DFL.

Так ли это?
Если да, то как поступить?

Кто знает прошу ответить.


Если генерация сигнала и произойдёт, то внутри одного из вызовов write/read..., т.е. СИНХРОННО, и такой сигнал уйдёт в IGN. Если я прав, то не опасно.

kiverattes ★☆
()
Ответ на: комментарий от kiverattes

kiverattes
Обнадеживает.
Но Вы сами не уверены. Точно ли так.

oleg_2
() автор топика

безопасно.

после close(fd) этот socket не может сгенерировать SIGPIPE.

Сигнал распространяется не мгновенно


в данном случае - «мгновенно». процесс не может вернуться
в user-space после syscall c signal_pending().

но,

Но при этом должны действовать какие-нибудь другие SIGPIPE


они, ессно, будут потеряны. лучше пользоваться MSG_NOSIGNAL.


хмм... честно говоря, я думал, что должен быть какой-то
setsockopt() который задавит этот дурацкий SIGPIPE, но
что-то не вижу.

idle ★★★★★
()
Ответ на: комментарий от xydo

> в однопоточном приложении это должно работать

в данном случае это не важно. этот сигнал посылается
потоку, а не процессу.

idle ★★★★★
()
Ответ на: комментарий от idle

Спасибо.
Убедили.
Однопоточный.
И за подсказку про MSG_NOSIGNAL спасибо.
Не пользовался раньше MSG_NOSIGNAL. Не было нужды.
Опробую, и, возможно, применю.

oleg_2
() автор топика

> Руководитель потребовал, чтобы при возврате из функции установить исходную, т. е. дефолтную реакцию на SIGPIPE.

Исходная и дефолтная - не одно и тоже ведь.

Sorcerer ★★★★★
()
Ответ на: комментарий от oleg_2

По случаю спасибо
idle
mky
за ответы в теме [СИ] прервать процесс.
(http://www.linux.org.ru/forum/development/5833957?lastmod=1296162836128#comme...)
Там речь шла о прерывании процесса, подвисшего на fcntl.
Я, хоть и с опозданием, но прочитал эти ответы.
Они вывели меня из заблуждения.

Обидно только, что такое удобное средство взаимодействия fcntl
(не родственные процессы, автоматическое снятие блокировки)
имеет такой недостаток.

oleg_2
() автор топика
Ответ на: комментарий от oleg_2

>Там речь шла о прерывании процесса, подвисшего на fcntl.

Честно говоря, так толком и не понял, чем вам не понравилось озвученное там предложение установить пустой обработчик сигнала и обработать rc=-1 от fcntl. Аргумент, что сигнал может придти до fcntl() можно распространить до аргумента, что сигнал может придти и до signal(). С какой стати программе накапливать информацию о сигналах? Пользователь, если ему будет нужно, нажмет INTR key повторно.

Murr ★★
()
Ответ на: комментарий от Murr

Murr
«что сигнал может придти и до signal()»
До signal() не страшно. Там код не критический.

«нажмет INTR key повторно»
Там много однотипных рабочих процессов (до 100). Демонов, т. е. без терминала.
Все рабочие процессы конечны, но иногда по долго зависают на блокировке.
И правильно. Это соответствует замыслу.

В программе есть кусок кода (main), который я называю пусковым модулем.
Когда я даю команду
./progr.cgi stop
этот пусковой модуль всем процессам посылает SIGINT.
Но сейчас это возможно только однократно. Pid-файл опустошается.

Можно ли сделать по другому? Думаю можно, и сделаю со временем.
Можно предусмотреть многократный stop.
Можно посылать сигнал мастер-процессу, который уже должен расправиться
с потомками.

Но fcntl то как опозорился.
Не могу дать ссылку, но и здесь, на форуме я читал сетование
на ограниченность fcntl. А теперь и сам столкнулся.

oleg_2
() автор топика
Ответ на: комментарий от Murr

> Пользователь, если ему будет нужно, нажмет INTR key повторно.

хех. это неспортивно ;)

если так рассуждать, то напр pselect() не нужен, пользователь
может послать сигнал еще раз, если ему надо.

или вот bug в bash c потерей ^C... конечно, пользователь
нажмет INTR key повторно, но некоторым пользователям это
не нравится.

idle ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.