Back to index

glibc  2.9
tst-signal3.c
Go to the documentation of this file.
00001 /* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
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 <errno.h>
00021 #include <pthread.h>
00022 #include <semaphore.h>
00023 #include <signal.h>
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026 #include <unistd.h>
00027 
00028 
00029 /* Number of different signalss to use.  Also is the number of
00030    threads.  */
00031 #define N 10
00032 /* Maximum number of threads in flight at any one time.  */
00033 #define INFLIGHT 5
00034 /* Number of signals sent in total.  */
00035 #define ROUNDS 10000
00036 
00037 
00038 static int received[N][N];
00039 static int nsig[N];
00040 static pthread_t th[N];
00041 static sem_t sem;
00042 static pthread_mutex_t lock[N];
00043 static pthread_t th_main;
00044 static int sig0;
00045 
00046 static void
00047 handler (int sig)
00048 {
00049   int i;
00050   for (i = 0; i < N; ++i)
00051     if (pthread_equal (pthread_self (), th[i]))
00052       break;
00053 
00054   if (i == N)
00055     {
00056       if (pthread_equal (pthread_self (), th_main))
00057        puts ("signal received by main thread");
00058       else
00059        printf ("signal received by unknown thread (%lx)\n",
00060               (unsigned long int) pthread_self ());
00061       exit (1);
00062     }
00063 
00064   ++received[i][sig - sig0];
00065 
00066   sem_post (&sem);
00067 }
00068 
00069 
00070 static void *
00071 tf (void *arg)
00072 {
00073   int idx = (long int) arg;
00074 
00075   sigset_t ss;
00076   sigemptyset (&ss);
00077 
00078   int i;
00079   for (i = 0; i <= idx; ++i)
00080     sigaddset (&ss, sig0 + i);
00081 
00082   if (pthread_sigmask (SIG_UNBLOCK, &ss, NULL) != 0)
00083     {
00084       printf ("thread %d: pthread_sigmask failed\n", i);
00085       exit (1);
00086     }
00087 
00088   pthread_mutex_lock (&lock[idx]);
00089 
00090   return NULL;
00091 }
00092 
00093 
00094 static int
00095 do_test (void)
00096 {
00097   /* Block all signals.  */
00098   sigset_t ss;
00099   sigfillset (&ss);
00100 
00101   th_main = pthread_self ();
00102 
00103   sig0 = SIGRTMIN;
00104 
00105   if (pthread_sigmask (SIG_SETMASK, &ss, NULL) != 0)
00106     {
00107       puts ("1st pthread_sigmask failed");
00108       exit (1);
00109     }
00110 
00111   /* Install the handler.  */
00112   int i;
00113   for (i = 0; i < N; ++i)
00114     {
00115       struct sigaction sa =
00116        {
00117          .sa_handler = handler,
00118          .sa_flags = 0
00119        };
00120       sigfillset (&sa.sa_mask);
00121 
00122       if (sigaction (sig0 + i, &sa, NULL) != 0)
00123        {
00124          printf ("sigaction for signal %d failed\n", i);
00125          exit (1);
00126        }
00127     }
00128 
00129   if (sem_init (&sem, 0, INFLIGHT) != 0)
00130     {
00131       puts ("sem_init failed");
00132       exit (1);
00133     }
00134 
00135   pthread_attr_t a;
00136 
00137   if (pthread_attr_init (&a) != 0)
00138     {
00139       puts ("attr_init failed");
00140       exit (1);
00141     }
00142 
00143   if (pthread_attr_setstacksize (&a, 1 * 1024 * 1024) != 0)
00144     {
00145       puts ("attr_setstacksize failed");
00146       return 1;
00147     }
00148 
00149   for (i = 0; i < N; ++i)
00150     {
00151       if (pthread_mutex_init (&lock[i], NULL) != 0)
00152        {
00153          printf ("mutex_init[%d] failed\n", i);
00154        }
00155 
00156       if (pthread_mutex_lock (&lock[i]) != 0)
00157        {
00158          printf ("mutex_lock[%d] failed\n", i);
00159        }
00160 
00161       if (pthread_create (&th[i], &a, tf, (void *) (long int) i) != 0)
00162        {
00163          printf ("create of thread %d failed\n", i);
00164          exit (1);
00165        }
00166     }
00167 
00168   if (pthread_attr_destroy (&a) != 0)
00169     {
00170       puts ("attr_destroy failed");
00171       exit (1);
00172     }
00173 
00174   int result = 0;
00175   unsigned int r = 42;
00176   pid_t pid = getpid ();
00177 
00178   for (i = 0; i < ROUNDS; ++i)
00179     {
00180       if (TEMP_FAILURE_RETRY (sem_wait (&sem)) != 0)
00181        {
00182          printf ("sem_wait round %d failed: %m\n", i);
00183          exit (1);
00184        }
00185 
00186       int s = rand_r (&r) % N;
00187 
00188       kill (pid, sig0 + s);
00189     }
00190 
00191   void *status;
00192   for (i = 0; i < N; ++i)
00193     {
00194       if (pthread_mutex_unlock (&lock[i]) != 0)
00195        {
00196          printf ("unlock %d failed\n", i);
00197          exit (1);
00198        }
00199 
00200       if (pthread_join (th[i], &status) != 0)
00201        {
00202          printf ("join %d failed\n", i);
00203          result = 1;
00204        }
00205       else if (status != NULL)
00206        {
00207          printf ("%d: result != NULL\n", i);
00208          result = 1;
00209        }
00210     }
00211 
00212   int total = 0;
00213   for (i = 0; i < N; ++i)
00214     {
00215       int j;
00216 
00217       for (j = 0; j <= i; ++j)
00218        total += received[i][j];
00219 
00220       for (j = i + 1; j < N; ++j)
00221        if (received[i][j] != 0)
00222          {
00223            printf ("thread %d received signal SIGRTMIN+%d\n", i, j);
00224            result = 1;
00225          }
00226     }
00227 
00228   if (total != ROUNDS)
00229     {
00230       printf ("total number of handled signals is %d, expected %d\n",
00231              total, ROUNDS);
00232       result = 1;
00233     }
00234 
00235   printf ("A total of %d signals sent and received\n", total);
00236   for (i = 0; i < N; ++i)
00237     {
00238       printf ("thread %2d:", i);
00239 
00240       int j;
00241       for (j = 0; j <= i; ++j)
00242        {
00243          printf (" %5d", received[i][j]);
00244          nsig[j] += received[i][j];
00245        }
00246 
00247       putchar ('\n');
00248 
00249     }
00250 
00251   printf ("\nTotal    :");
00252   for (i = 0; i < N; ++i)
00253     printf (" %5d", nsig[i]);
00254   putchar ('\n');
00255 
00256   return result;
00257 }
00258 
00259 #define TIMEOUT 10
00260 #define TEST_FUNCTION do_test ()
00261 #include "../test-skeleton.c"