UNIX: разработка сетевых приложений | страница 13



1.4. Обработка ошибок: функции-обертки

В любой реальной программе существенным моментом является проверка каждого вызова функции на предмет возвращаемой ошибки. В листинге 1.1 мы проводим поиск ошибок в вызовах функций >socket, >inet_pton, >connect, >read и >fputs, и когда ошибка случается, мы вызываем свои собственные функции >err_quit и >err_sys для печати сообщения об ошибке и для прерывания выполнения программы. В отдельных случаях, когда функция возвращает ошибку, бывает нужно сделать еще что-либо помимо прерывания программы, как показано в листинге 5.9, когда мы должны проверить прерванный системный вызов.

Поскольку прерывание программы из-за ошибки — типичное явление, мы сократим наши программы, определив функции-обертки, которые будут вызывать соответствующие рабочие функции, проверять возвращаемые значения и прерывать программу при возникновении ошибки. Соглашение, используемое нами, заключается в том, что название функции-обертки пишется с заглавной буквы, например:

>sockfd = Socket(AF_INET, SOCK_STREAM, 0);

Наша функция-обертка для функции socket показана в листинге 1.3.

Листинг 1.3. Наша функция-обертка для функции socket

>//lib/wrapsock.c

>172 int

>173 Socket(int family, int type, int protocol)

>174 {

>175  int n;


>176  if ((n = socket(family, type, protocol)) < 0)

>177   err_sys("socket error");

>178  return (n);

>179 }

Хотя вы можете решить, что использование этих функций-оберток не обеспечивает большой экономии, на самом деле это не так. Обсуждая потоки (threads) в главе 26, мы обнаружим, что, когда происходит какая-либо ошибка, функции потоков не устанавливают значение стандартной переменной Unix >errno равным определенной константе, специфической для произошедшей ошибки. Вместо этого значение переменной >errno просто возвращается функцией. Это значит, что каждый раз, когда мы вызываем одну из функций >pthread, мы должны разместить в памяти переменную, сохранить возвращаемое значение в этой переменной и установить >errno равной этому значению перед вызовом >err_sys. Чтобы избежать загромождения кода скобками, мы можем использовать оператор языка С запятая для объединения присваивания значения переменной >errno и вызова >err_sys в отдельное выражение следующим образом:

>int n;

>if ((n = pthread_mutex_lock(&ndone_mutex)) != 0)

> errno = n, err_sys("pthread_mutex_lock error");

ВНИМАНИЕ

В тексте книги вам будут встречаться функции, имена которые начинаются с заглавной буквы. Это наши собственные функции-обертки. Функция-обертка вызывает функцию, имеющую такое же имя, но начинающееся со строчной буквы.