Back to index

glibc  2.9
tst-cancel8.c
Go to the documentation of this file.
00001 /* Copyright (C) 2003 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003    Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <pthread.h>
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <unistd.h>
00024 
00025 
00026 static pthread_barrier_t bar;
00027 
00028 static int global;
00029 
00030 
00031 static void
00032 cleanup (void *arg)
00033 {
00034   global = 1;
00035 }
00036 
00037 
00038 static void *
00039 tf (void *arg)
00040 {
00041   /* Enable cancellation, but defer it.  */
00042   if (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL) != 0)
00043     {
00044       puts ("setcancelstate failed");
00045       exit (1);
00046     }
00047   if (pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, NULL) != 0)
00048     {
00049       puts ("setcanceltype failed");
00050       exit (1);
00051     }
00052 
00053   /* Add cleanup handler.  */
00054   pthread_cleanup_push (cleanup, NULL);
00055 
00056   /* Synchronize with the main thread.  */
00057   int r = pthread_barrier_wait (&bar);
00058   if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
00059     {
00060       puts ("tf: first barrier_wait failed");
00061       exit (1);
00062     }
00063 
00064   /* And again.  Once this is done the main thread should have canceled
00065      this thread.  */
00066   r = pthread_barrier_wait (&bar);
00067   if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
00068     {
00069       puts ("tf: second barrier_wait failed");
00070       exit (1);
00071     }
00072 
00073   /* Remove the cleanup handler without executing it.  */
00074   pthread_cleanup_pop (0);
00075 
00076   /* Now react on the cancellation.  */
00077   pthread_testcancel ();
00078 
00079   /* This call should never return.  */
00080   return NULL;
00081 }
00082 
00083 
00084 static int
00085 do_test (void)
00086 {
00087   if (pthread_barrier_init (&bar, NULL, 2) != 0)
00088     {
00089       puts ("barrier_init failed");
00090       exit (1);
00091     }
00092 
00093   pthread_t th;
00094   if (pthread_create (&th, NULL, tf, NULL) != 0)
00095     {
00096       puts ("pthread_create failed");
00097       return 1;
00098     }
00099 
00100   int r = pthread_barrier_wait (&bar);
00101   if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
00102     {
00103       puts ("first barrier_wait failed");
00104       exit (1);
00105     }
00106 
00107   if (pthread_cancel (th) != 0)
00108     {
00109       puts ("pthread_cancel failed");
00110       return 1;
00111     }
00112 
00113   r = pthread_barrier_wait (&bar);
00114   if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
00115     {
00116       puts ("second barrier_wait failed");
00117       exit (1);
00118     }
00119 
00120   void *result;
00121   if (pthread_join (th, &result) != 0)
00122     {
00123       puts ("pthread_join failed");
00124       return 1;
00125     }
00126 
00127   if (result != PTHREAD_CANCELED)
00128     {
00129       puts ("thread was not canceled");
00130       exit (1);
00131     }
00132 
00133   if (global != 0)
00134     {
00135       puts ("cancellation handler has been called");
00136       exit (1);
00137     }
00138 
00139   return 0;
00140 }
00141 
00142 #define TEST_FUNCTION do_test ()
00143 #include "../test-skeleton.c"