Чтение онлайн

на главную

Жанры

UNIX: взаимодействие процессов

Стивенс Уильям Ричард

Шрифт:

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

Изменим сервер так, чтобы он выводил идентификатор вызванного потока, делал паузу в 6 секунд и выводил идентификатор потока по завершении его. В листинге 15.23 приведен текст новой процедуры сервера. 

Листинг 15.23. Процедура сервера, выводящая свой идентификатор потока дважды

//doors/serverintr3.c

1 #include "unpipc.h"

2 void

3 servproc(void *cookie, char *dataptr, size_t datasize,

4 door_desc_t *descptr, size_t ndesc)

5 {

6 long arg, result:

7 printf("thread id %ld called\n", pr_thread_id(NULL));

8 sleep(6); /* даем клиенту возможность перехватить SIGCHLD */

9 arg = *((long*)dataptr);

10 result = arg * arg;

11 printf("thread id %ld returning\n", pr_thread_id(NULL));

12 Door_return((char *) &result, sizeof(result), NULL, 0);

13 }

В листинге 15.24 приведен текст программы-клиента.

Листинг 15.24. Клиент, вызывающий door_call еще раз, после перехвата EINTR

//doors/clientintr3.c

1 #include "unpipc.h"

2 volatile sig_atomic_t caught_sigchld;

3 void

4 sig_chld(int signo)

5 {

6 caught_sigchld = 1;

7 return; /* прерываем вызов door_call */

8 }

9 int

10 main(int argc, char **argv)

11 {

12 int fd, rc;

13 long ival, oval;

14 door_arg_t arg;

15 if (argc != 3)

16 err_quit("usage: clientintr3 <server-pathname> <integer-value>");

17 fd = Open(argv[1], O_RDWR); /* открытие двери */

18 /* подготовка аргументов и указателя на результаты */

19 ival = atol(argv[2]);

20 arg.data_ptr = (char*)&ival; /* аргументы */

21 arg.data_size = sizeof(long); /* размер аргументов */

22 arg.desc_ptr = NULL;

23 arg.desc_num = 0;

24 arg.rbuf = (char*)&oval; /* возвращаемые данные */

25 arg.rsize = sizeof(long); /* размер данных */

26 Signal(SIGCHLD, sig_chld);

27 if (Fork == 0) {

28 sleep(2); /* дочерний процесс */

29 exit(0); /* отправка SIGCHLD */

30 }

31 /* родительский процесс : вызов процедуры сервера и вывод результата */

32 for (;;) {

33 printf("calling door_call\n");

34 if ((rc = door_call(fd, &arg)) == 0)

35 break; /* успешное завершение */

36 if (errno == EINTR && caught_sigchld) {

37 caught_sigchld = 0;

38 continue; /* повторный вызов door_call */

39 }

40 err_sys("door_call error");

41 }

42 printf("result: %ld\n", oval);

43 exit(0);

44 }

2-8 Объявляем глобальную переменную caught_sigchld, устанавливая ее в единицу при перехвате сигнала SIGCHLD.

31-42 Вызываем door_call в цикле, пока он не завершится успешно.

Глядя на выводимые клиентом результаты, мы можем подумать, что все в порядке:

solaris % clientintr3 /tmp/door3 33

calling door_call

calling door_call

result: 1089

Функция door_call вызывается в первый раз, обработчик сигнала срабатывает через 2 секунды после этого и переменной caught_sigchld присваивается значение 1. door_call при этом возвращает ошибку EINTR и мы вызываем door_call еще раз. Во второй раз процедура завершается успешно.

Посмотрев на выводимый сервером текст, мы увидим, что процедура сервера была вызвана дважды:

solaris % serverintr3 /tmp/door3

thread id 4 called

thread id 4 returning

thread id 5 called

thread id 5 returning

Когда клиент второй раз вызывает door_call, это приводит к запуску нового потока, вызывающего процедуру сервера еще раз. Если процедура сервера идемпотентна, проблем в такой ситуации не возникнет. Однако если она неидемпотентна, это может привести к ошибкам.

Термин «идемпотентность» по отношению к процедуре подразумевает, что процедура может быть вызвана произвольное число раз без возникновения ошибок. Наша процедура сервера, вычисляющая квадрат целого числа, идемпотентна: мы получаем правильный результат вне зависимости от того, сколько раз мы ее вызовем. Другим примером является процедура, возвращающая дату и время. Хотя эта процедура и будет возвращать разную информацию при новых вызовах (поскольку дата и время меняются), это не вызовет проблем. Классическим примером неидемпотентной процедуры является процедура уменьшения банковского счета на некоторую величину. Конечный результат будет неверным, если ее вызвать дважды.

Поделиться:
Популярные книги

Хозяин Теней

Петров Максим Николаевич
1. Безбожник
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Хозяин Теней

Кукловод

Майерс Александр
4. Династия
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Кукловод

#Бояръ-Аниме. Газлайтер. Том 24

Володин Григорий Григорьевич
24. История Телепата
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
#Бояръ-Аниме. Газлайтер. Том 24

Снега

Чепурин Юлий Петрович
Поэзия:
драматургия
5.00
рейтинг книги
Снега

Матабар III

Клеванский Кирилл Сергеевич
3. Матабар
Фантастика:
фэнтези
5.00
рейтинг книги
Матабар III

Я все еще царь. Книга XXXI

Дрейк Сириус
31. Дорогой барон!
Фантастика:
юмористическое фэнтези
аниме
попаданцы
5.00
рейтинг книги
Я все еще царь. Книга XXXI

Базис

Владимиров Денис
7. Глэрд
Фантастика:
фэнтези
боевая фантастика
попаданцы
5.00
рейтинг книги
Базис

Я еще не бог. Книга XXXV

Дрейк Сириус
35. Дорогой барон!
Фантастика:
аниме
попаданцы
5.00
рейтинг книги
Я еще не бог. Книга XXXV

Вторая жизнь майора. Цикл

Сухинин Владимир Александрович
Вторая жизнь майора
Фантастика:
героическая фантастика
боевая фантастика
попаданцы
5.00
рейтинг книги
Вторая жизнь майора. Цикл

Гранд

Демченко Антон Витальевич
3. Воздушный стрелок
Фантастика:
боевая фантастика
8.12
рейтинг книги
Гранд

Идеальный мир для Лекаря 23

Сапфир Олег
23. Лекарь
Фантастика:
юмористическое фэнтези
аниме
фэнтези
5.00
рейтинг книги
Идеальный мир для Лекаря 23

Мятежник

Прокофьев Роман Юрьевич
4. Стеллар
Фантастика:
боевая фантастика
7.39
рейтинг книги
Мятежник

Страж Кодекса. Книга V

Романов Илья Николаевич
5. КО: Страж Кодекса
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Страж Кодекса. Книга V

На границе империй. Том 8

INDIGO
12. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 8