с / форк / сигналы / лучшие практики закрытия открытых розеток в разных процессах - PullRequest
1 голос
/ 19 мая 2011

Здравствуйте,

за два дня до того, как я спросил о нитях и вилке.Теперь я использовал методы fork.При создании второго процесса родитель и потомок выполняют разный код, но оба заканчивают циклом while, потому что один отправляет навсегда пакеты через сокет, а другой постоянно слушает в сокете.Теперь я хочу, чтобы они очистились при нажатии ctrl-c, т.е. оба должны закрыть свои открытые сокеты перед возвратом.

У меня есть три файла, первый - основной файл создает процессы.Во втором файле записан родительский код, в третьем дочерний код.Дополнительную информацию (фрагменты кода) вы можете найти здесь: c / прерванный системный вызов / ответвление против потока

Теперь мой вопрос, куда мне поместить обработчик сигнала или сделатьЯ должен указать два из них, по одному для каждого процесса?Это кажется простым вопросом, но не для меня как-то.Я пробовал разные способы.Но смог сделать только одного из парней успешным, чтобы очистить перед возвращением (мой английский плохо, поэтому извините).оба должны делать разные вещи, это проблема для меня, поэтому одного обработчика будет недостаточно, верно?

struct sigaction new_action;
new_action.sa_handler = termination_handler_1;
sigemptyset (&new_action.sa_mask);
new_action.sa_flags = 0;
sigaction(SIGINT, &new_action, NULL);

....more code here ... 

/* will run until crtl-c is pressed */
while(keep_going) {
    recvlen = recvfrom(sockfd_in, msg, itsGnMaxSduSize_MIB, 0, (struct sockaddr *) &incoming, &ilen);
    if(recvlen < 0) {
        perror("something went wrong / incoming\n");
        exit(1);
    }

    buflen = strlen(msg);
    sentlen = ath_sendto(sfd, &athinfo, &addrnwh, &nwh,  buflen, msg, &selpv2, &depv);

    if(sentlen == E_ERR) {
        perror("Failed to send network header packet.\n");
        exit(1);
    }
}

close(sockfd_in);
/* Close network header socket */
gnwh_close(sfd);
/* Terminate network header library */
gnwh_term();
printf("pc2wsu: signal received, closed all sockets and so on!\n");
return 0;
}


void termination_handler_1(wuint32 signum) {
    keep_going = 0;
}

Как видите, обработка сигнала в моем случае просто меняет условие цикла "keep_going".После выхода из цикла каждый процесс должен очиститься.

Заранее спасибо за вашу помощь.nyyrikki

Ответы [ 2 ]

2 голосов
/ 19 мая 2011

Нет причин закрывать розетки. Когда процесс завершается (как действие по умолчанию для SIGINT), все его файловые дескрипторы по своей сути закрываются. Если у вас нет другой необходимой очистки (например, сохранение данных на диск), тогда забудьте о обработке сигнала вообще. Это почти наверняка неправильно.

1 голос
/ 19 мая 2011

Ваш код страдает от состояния гонки. Вы проверяете keep_going и затем вводите recvfrom, но он мог получить сигнал между ними. Это маловероятно, поэтому мы проигнорируем это.

Похоже, что отправитель и получатель были запущены одним и тем же процессом, и этот процесс был запущен из оболочки. Если вы ничего не сделали, они будут в одной группе процессов, и все три процесса получат SIGINT, когда вы нажмете ^ C. Таким образом, было бы лучше, если бы оба процесса обрабатывали SIGINT, если вы хотите запустить код очистки (обратите внимание, закрытие FD не является веской причиной ... fds будет автоматически закрываться при выходе из процесса). Если это TCP-сокеты между двумя, закрытие одной стороны в конечном итоге приведет к закрытию другой стороны (но для отправителя, пока они не попытаются отправить снова).

...