| /* Tests for cancelation handling. */ |
| |
| #include <pthread.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <unistd.h> |
| #include <sys/stat.h> |
| |
| int fd; |
| |
| pthread_barrier_t bar; |
| |
| |
| static void |
| cleanup (void *arg) |
| { |
| int nr = (int) (long int) arg; |
| char s[30]; |
| char *cp = stpcpy (s, "cleanup "); |
| *cp++ = '0' + nr; |
| *cp++ = '\n'; |
| __libc_lseek (fd, 0, SEEK_END); |
| __libc_write (fd, s, cp - s); |
| } |
| |
| |
| static void * |
| t1 (void *arg) |
| { |
| pthread_cleanup_push (cleanup, (void *) (long int) 1); |
| return NULL; |
| pthread_cleanup_pop (0); |
| } |
| |
| |
| static void |
| inner (int a) |
| { |
| pthread_cleanup_push (cleanup, (void *) (long int) a); |
| if (a) |
| return; |
| pthread_cleanup_pop (0); |
| } |
| |
| |
| static void * |
| t2 (void *arg) |
| { |
| pthread_cleanup_push (cleanup, (void *) (long int) 2); |
| inner ((int) (long int) arg); |
| return NULL; |
| pthread_cleanup_pop (0); |
| } |
| |
| |
| /* This does not work yet. */ |
| volatile int cleanupokcnt; |
| |
| static void |
| cleanupok (void *arg) |
| { |
| ++cleanupokcnt; |
| } |
| |
| |
| static void * |
| t3 (void *arg) |
| { |
| pthread_cleanup_push (cleanupok, (void *) (long int) 4); |
| inner ((int) (long int) arg); |
| pthread_exit (NULL); |
| pthread_cleanup_pop (0); |
| } |
| |
| |
| static void |
| innerok (int a) |
| { |
| pthread_cleanup_push (cleanupok, (void *) (long int) a); |
| pthread_exit (NULL); |
| pthread_cleanup_pop (0); |
| } |
| |
| |
| static void * |
| t4 (void *arg) |
| { |
| pthread_cleanup_push (cleanupok, (void *) (long int) 6); |
| innerok ((int) (long int) arg); |
| pthread_cleanup_pop (0); |
| return NULL; |
| } |
| |
| |
| int |
| main (int argc, char *argv[]) |
| { |
| pthread_t td; |
| int err; |
| char *tmp; |
| const char *prefix; |
| const char template[] = "thtstXXXXXX"; |
| struct stat64 st; |
| int result = 0; |
| |
| prefix = argc > 1 ? argv[1] : ""; |
| tmp = (char *) alloca (strlen (prefix) + sizeof template); |
| strcpy (stpcpy (tmp, prefix), template); |
| |
| fd = mkstemp (tmp); |
| if (fd == -1) |
| { |
| printf ("cannot create temporary file: %m"); |
| exit (1); |
| } |
| unlink (tmp); |
| |
| err = pthread_barrier_init (&bar, NULL, 2); |
| if (err != 0 ) |
| { |
| printf ("cannot create barrier: %s\n", strerror (err)); |
| exit (1); |
| } |
| |
| #ifdef NOT_YET |
| err = pthread_create (&td, NULL, t1, NULL); |
| if (err != 0) |
| { |
| printf ("cannot create thread t1: %s\n", strerror (err)); |
| exit (1); |
| } |
| |
| err = pthread_join (td, NULL); |
| if (err != 0) |
| { |
| printf ("cannot join thread: %s\n", strerror (err)); |
| exit (1); |
| } |
| |
| err = pthread_create (&td, NULL, t2, (void *) 3); |
| if (err != 0) |
| { |
| printf ("cannot create thread t2: %s\n", strerror (err)); |
| exit (1); |
| } |
| |
| err = pthread_join (td, NULL); |
| if (err != 0) |
| { |
| printf ("cannot join thread: %s\n", strerror (err)); |
| exit (1); |
| } |
| |
| err = pthread_create (&td, NULL, t3, (void *) 5); |
| if (err != 0) |
| { |
| printf ("cannot create thread t3: %s\n", strerror (err)); |
| exit (1); |
| } |
| |
| err = pthread_join (td, NULL); |
| if (err != 0) |
| { |
| printf ("cannot join thread: %s\n", strerror (err)); |
| exit (1); |
| } |
| #endif |
| |
| err = pthread_create (&td, NULL, t4, (void *) 7); |
| if (err != 0) |
| { |
| printf ("cannot create thread t3: %s\n", strerror (err)); |
| exit (1); |
| } |
| |
| err = pthread_join (td, NULL); |
| if (err != 0) |
| { |
| printf ("cannot join thread: %s\n", strerror (err)); |
| exit (1); |
| } |
| |
| if (fstat64 (fd, &st) < 0) |
| { |
| printf ("cannot stat temporary file: %m\n"); |
| result = 1; |
| } |
| else if (st.st_size != 0) |
| { |
| char buf[512]; |
| puts ("some cleanup handlers ran:"); |
| fflush (stdout); |
| __lseek (fd, 0, SEEK_SET); |
| while (1) |
| { |
| ssize_t n = read (fd, buf, sizeof buf); |
| if (n <= 0) |
| break; |
| write (STDOUT_FILENO, buf, n); |
| } |
| result = 1; |
| } |
| |
| // if (cleanupokcnt != 3) will be three once t3 runs |
| if (cleanupokcnt != 2) |
| { |
| printf ("cleanupokcnt = %d\n", cleanupokcnt); |
| result = 1; |
| } |
| |
| return result; |
| } |