Книга: Programming with POSIX® Threads

5.3.1 Deferred cancelability

5.3.1 Deferred cancelability

"Deferred cancelability" means that the thread's cancelability type has been set to PTHREAD_CANCEL_DEFERRED and the thread's cancelability enable has been set to PTHREAD_CANCEL_ENABLE. The thread will only respond to cancellation requests when it reaches one of a set of "cancellation points."

The following functions are always cancellation points on any Pthreads system:

pthread_cond_wait  fsync

pthread_cond_timedwait mq_receive pthread_join mq_send

pthread_testcancel msync

sigwait nanosleep

aio_suspend open

close pause

creat read

fcntl (F_SETLCKW) sem_wait

The following list of functions may be cancellation points. You should write your code so that it will function correctly if any of these are cancellation points

sigwaitinfo

sigsuspend

sigtimedwait

sleep

system

tcdrain

wait

waitpid

write

and also so that it will not break if any of them are not. If you depend upon any particular behavior, you may limit the portability of your code. You'll have to look at the conformance documentation to find out which, if any, are cancellation points for the system you are using:

closedir getc_unlocked printf
ctermid getchar putc
fclose getchar_unlocked putc_unlocked
fcntl (except F_SETLCKW) getcwd putchar
fflush getgrgid putchar_unlocked
fgetc getgrgid_r puts
fgets getrtnam readdir
fopen getgrnam_r remove
fprintf getlogin rename
fputc getlogin_r rewind
fputs getpwnam rewinddir
fread getpwnam_r scanf
freopen getpwuid tmpfile
fscanf getpwuid_r tmpname
fseek gets ttyname
ftell lseek ttyname_r
fwrite opendir ungetc
getc perror

Pthreads specifies that any ANSI C or POSIX function not specified in one of the two lists cannot be a cancellation point. However, your system probably has many additional cancellation points. That's because few UNIX systems are "POSIX." That is, they support other programming interfaces as well — such as BSD 4.3, System V Release 4, UNLX95, and so forth. POSIX doesn't recognize the existence of functions such as select or poll, and therefore it can't say whether or not they are cancellation points. Yet clearly both are functions that may block for an arbitrary period of time, and programmers using them with cancellation would reasonably expect them to behave as cancellation points. X/Open is currently addressing this problem for UNLX98 (X/Open System Interfaces, Issue 5). by extending the Pthreads list of cancellation points.

Most cancellation points involve I/O operations that may block the thread for an "unbounded" time. They're cancelable so that the waits can be interrupted. When a thread reaches a cancellation point the system determines whether a cancel is pending for the current ("target") thread. A cancel will be pending if another thread has called pthread_cancel for the target thread since the last time the target thread returned from a cancellation point. If a cancel is pending, the system will immediately begin calling cleanup functions, and then the thread will terminate.

If no cancel is currently pending, the function will proceed. If another thread requests that the thread be canceled while the thread is waiting for something (such as I/O) then the wait will be interrupted and the thread will begin its cancellation cleanup.

If you need to ensure that cancellation can't occur at a particular cancellation point, or during some sequence of cancellation points, you can temporarily disable cancellation in that region of code. The following program, called cancel_ disable.c, is a variant of cancel.c. The "target" thread periodically calls sleep, and does not want the call to be cancelable.

23-32 After each cycle of 755 iterations, thread_routine will call sleep to wait a second. (The value 755 is just an arbitrary number that popped into my head. Do arbitrary numbers ever pop into your head?) Prior to sleeping, thread_routine disables cancellation by setting the cancelability state to PTHREAD_CANCEL_ DISABLE. After sleep returns, it restores the saved cancelability state by calling pthread_setcancelstate again.

33-35 Just as in cancel.c, test for a pending cancel every 1000 iterations.

? cancel_disable.c

1 #include <pthread.h>
2 #include "errors.h"
3
4 static int counter;
5
6 /*
7 * Thread start routine.
8 */
9 void *thread_routine (void *arg)
10 {
11 int state;
12 int status;

13
14 for (counter = 0; ; counter++) {

15
16 /*
17 * Each 755 iterations, disable cancellation and sleep
18 * for one second.
19 *
20 * Each 1000 iterations, test for a pending cancel by
21 * calling pthread_testcancel().
22 */
23 if ((counter % 755) == 0) {
24 status = pthread_setcancelstate (
25 PTHREAD_CANCEL_DISABLE, &state);
26 if (status != 0)
27 err_abort (status, "Disable cancel");
28 sleep (1);
29 status = pthread_setcancelstate (
30 state, &state);
31 if (status != 0)
32 err_abort (status, "Restore cancel");
33 } else
34 if ((counter % 1000) == 0)
35 pthread_testcancel ();
36 }
37 }

38
39 int main (int argc, char *argv[])
40 {
41 pthread_t thread_id;
42 void *result;
43 int status;

44
45 status = pthread_create (
46 &thread_id, NULL, thread_routine, NULL);
47 if (status != 0)
48 err_abort (status, "Create thread");
49 sleep (2);
50 status = pthread_cancel (thread_id);
51 if (status != 0)
52 err_abort (status, "Cancel thread");

53
54 status = pthread_join (thread_id, &result);
55 if (status != 0)
56 err_abort (status, "Join thread");
57 if (result == PTHREAD_CANCELED)
58 printf ("Thread canceled at iteration %dn", counter);
59 else
60 printf ("Thread was not canceledn");
61 return 0;
62 }

Оглавление книги


Генерация: 2.024. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз