Вход/Регистрация
UNIX: взаимодействие процессов
вернуться

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

Шрифт:

Досрочное завершение клиента

Посмотрим, каким образом процедура сервера получает уведомление о досрочном завершении клиента. Пpoгрaммa-клиeнт приведена в листинге 15.25.

Листинг 15.25. Клиент, досрочно завершающий работу после вызова door_call

//doors/clientintr4.c

1 #include "unpipc.h"

2 int

3 main(int argc, char **argv)

4 {

5 int fd;

6 long ival, oval;

7 door_arg_t arg;

8 if (argc != 3)

9 err_quit("usage: clientintr4 <server-pathname> <integer-value>");

10 fd = Open(argv[1], O_RDWR); /* открываем дверь */

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

12 ival = atol(argv[2]);

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

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

15 arg.desc_ptr = NULL;

16 arg.desc_num = 0;

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

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

19 /* вызов процедуры сервера и вывод результата */

20 alarm(3);

21 Door_call(fd, &arg);

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

23 exit(0);

24 }

20 Единственное изменение заключается в добавлении вызова alarm(3) перед door_call. Эта функция приводит к отправке сигнала SIGALRM через три секунды после вызова, но, поскольку мы его не перехватываем, это приводит к завершению процесса. Поэтому клиент завершится до возврата из door_call, потому что в процедуру сервера вставлена шестисекундная пауза.

В листинге 15.26 приведен текст процедуры сервера и обработчик отмены потока.

Листинг 15.26. Процедура сервера, обрабатывающая досрочное завершение клиента

//doors/serverintr4.с

1 #include "unpipc.h"

2 void

3 servproc_cleanup(void *arg)

4 {

5 printf("servproc cancelled, thread id %ld\n", pr_thread_id(NULL));

6 }

7 void

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

9 door_desc_t *descptr, size_t ndesc)

10 {

11 int oldstate, junk;

12 long arg, result;

13 Pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);

14 pthread_cleanup_push(servproc_cleanup, NULL);

15 sleep(6);

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

17 result = arg * arg;

18 pthread_cleanup_pop(0);

19 Pthread_setcancelstate(oldstate, &junk);

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

21 }

Вспомните, что мы говорили об отмене выполнения потока в разделе 8.5 и в связи с листингом 15.18. Когда система обнаруживает завершение клиента в процессе выполнения серверной процедуры, потоку, обрабатывающему запрос этого клиента, отправляется запрос на отмену:

■ если поток отключил возможность отмены, ничего не происходит и поток выполняется до завершения (вызов door_return), а результаты сбрасываются;

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

В тексте процедуры сервера мы сначала вызвали pthread_setcancelstate для включения возможности отмены потока, потому что по умолчанию при создании новых потоков библиотекой возможность их отмены отключается. Эта функция сохраняет текущее состояние потока в переменной oldstate, и мы восстанавливаем его в конце функции. Затем мы вызываем pthread_cleanup_push для регистрации нашего обработчика отмены servproc_cleanup. Эта функция только выводит идентификатор отмененного потока, но вообще она может выполнять все необходимое для корректного завершения процедуры сервера (разблокировать исключения и т. п.). После возвращения из обработчика поток завершается.

  • Читать дальше
  • 1
  • ...
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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