LINUX.ORG.RU

accept() не прерывается сигналом


0

1

Документация говорит, что accept() должен прерваться после выполнения обработчика сигнала и вернуть -1. По какой причине accept() может не прерываться сигналом?

if (!_tcp_inited){
		int bind_res, listen_res;
		_sock = socket(AF_INET, SOCK_STREAM, 0);

		if (_sock < 0) return SYSTEM_ERR;
		struct sockaddr_in addr;//, client_addr;
		bzero(&addr, sizeof(addr));	
		addr.sin_family = AF_INET;
		addr.sin_port = _client->GetTCPPort();
		addr.sin_addr.s_addr = INADDR_ANY;
		bind_res = bind(_sock, (sockaddr*)&addr, sizeof(addr));
		if (bind_res != 0) return SYSTEM_ERR;
		listen_res = listen(_sock, 2);
		if (listen_res != 0) return SYSTEM_ERR;
		_tcp_inited = true;
	}
	
	struct sockaddr_in client_addr;
	socklen_t client_addr_len = sizeof(client_addr);
	printf("accept start\n");
	_fd = accept(_sock, (sockaddr*)&client_addr, &client_addr_len);
	
	printf("accept finish\n");
	//printf("accept ends\n");
	if (_fd < 0) return SYSTEM_ERR;
		
	return OK;

Подписка на событие:

void BCPDaemon::IntrHandler(int signum){
	_sig_stop = 1;
}

//TODO:write into log
int BCPDaemon::Init(){
	bsd_signal(SIGTSTP, SIG_IGN);
	bsd_signal(SIGINT, BCPDaemon::IntrHandler);
...
}

Система - Slackware 12.


> По какой причине accept() может не прерываться сигналом? Потому что сигнал перехватили вы?

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

Стивенс Unix. Разработка сетевых приложений. стр 159

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

Я пробовал вообще не подписываться на событие - в этом случае при сигнале SIGINT программа сразу дохнет, хотя как минимум должна быть надпись «accept finish».

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

Если bsd_signal действительно повторяет семантику bsd'шного signal'а, то прерванный сисколл должен перезапускаться автоматом. Юзай signal, sigaction, etc.

mv ★★★★★
()

> Документация говорит, что accept() должен прерваться

после выполнения обработчика сигнала и вернуть -1.


а где это сказано? даже интересно.

как уже было сказано, man sigaction (SA_RESTART).

и еще. сам я не проверял, но судя по
include/net/sock.h:sock_intr_errno() вы можете
установить SO_RCVTIMEO, и тогда будет EINTR.
(если я правильно понимаю inet_csk_wait_for_connect)

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

signal и bsd_signal

На старых системах (V7). была функция signal(), особенность её работы заключалась в том, что после перехвата события, происходил сброс подписки на событие и приходилось заново подписываться. В BSD все поменялось и тот же самый signal() уже не надо было каждый вызывать чтобы подписаться после срабатывания ловушки. Так вот bsd_signal() подчеркивает именно эту семантику, чтоб народ не путался. sigaction отличается только безопасностью вызова обработчика, пока обработчик не завершит работу, он не запускается (с некоторыми оговорками).

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

man accept

On error, -1 is returned, and errno is set appropriately.

errno: EINTR The system call was interrupted by a signal that was caught before a valid connection arrived; see signal(7).

Попробую sigaction и SO_RCVTIMEO.

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

> errno: EINTR The system call was interrupted by a signal that

was caught before a valid connection arrived; see signal(7).


нет, но это совершенно не означает, что accept() всегда
должен прерываться сигналом. здесь просто напоминают о
стандартном значении EINTR.

короче, man sigaction.

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

Пасибо!!! Да, действительно, signal и sigaction работают по-разному. После signal по-дефолту возобновляется выполнение функции, а в sigaction надо флаг указыватиь SA_RESTART, чтобы возобновлялось выполнение.

and73y
() автор топика
Ответ на: signal и bsd_signal от and73y

sigaction отличается только безопасностью вызова обработчика, пока обработчик не завершит работу, он не запускается (с некоторыми оговорками).

В sigaction можно флажок для рестарта поднять.

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