Можем ли мы передать параметры сигналам в C? - PullRequest
0 голосов
/ 14 марта 2011

Я реализую простой итеративный TCP клиент / сервер в C. Сервер бесконечно перечисляется в цикле.

Теперь, если Ctrl + c (SIGINT) произошел в любой момент времени, как бы я освободил ресурсы, используемые на сервере?

Например, я поймал сигнал в своем собственном обработчике сигналов; как бы я получить дескрипторы сокета и буферы, используемые в программе, чтобы освободить их?

Я новичок в программировании сокетов; любые предложения будут оценены.

Ответы [ 3 ]

2 голосов
/ 14 марта 2011

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

2 голосов
/ 14 марта 2011

Нет. Единственный параметр, передаваемый вашему обработчику сигнала, это int, который является номером сигнала.

Типичный способ справиться с описанной вами ситуацией - использовать глобальную переменную, такую ​​как int stopAndExit, которую проверяет ваш цикл. Если он обработан обработчиком сигнала, который, как вы знаете, очистит и выйдет на 1.

Редактировать: Для более подробного обсуждения, вызванного комментариями ниже.

Одна из проблем заключается в том, что при поступлении сигнала вы находитесь в нереентеральной функции. Чтобы справиться с этим, вы действительно хотите задержать (заблокировать) сигналы, а затем обработать их в точке вашего основного цикла, которая является безопасной.

Последнее редактирование: Если у вас не происходит каких-либо внешних операций, которые необходимо предварительно очистить, чтобы гарантировать выход в чистом состоянии ... это не имеет значения. Ваши дескрипторы сокетов и буферы все равно исчезают, когда вы выходите. Там не нужно ничего убирать.

0 голосов
/ 14 марта 2011

Код в этом ответе ужасно небезопасен, вызывает все виды UB и не должен использоваться в вашем случае. Использование setjmp / longjmp в обработчике сигналов возможно только удаленно, как способ справиться с разыменованием нулевого указателя, и даже в этом случае он должен быть чрезвычайно ограничен по объему, чтобы избежать вызова UB.

Вот еще один из возможных способов очистки:

static jmp_buf buf;
static int ret = 0;

void handle(int sig)
{
    ret = 1;
    longjmp(buf, 1);
}

int func(void)
{
    FILE *f = fopen(/* yadda */);

    void (*orig)(int) = signal(SIGINT, handle);

    if(setjmp(buf)) goto CLEANUP;

    // use f

  CLEANUP:
    fclose(f);
    signal(SIGINT, orig);
    return ret;
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...