Back to index

glibc  2.9
tst-mqueue6.c
Go to the documentation of this file.
00001 /* Test mq_notify.
00002    Copyright (C) 2004 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Contributed by Jakub Jelinek <jakub@redhat.com>, 2004.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 #include <errno.h>
00022 #include <fcntl.h>
00023 #include <mqueue.h>
00024 #include <limits.h>
00025 #include <signal.h>
00026 #include <stdint.h>
00027 #include <stdio.h>
00028 #include <stdlib.h>
00029 #include <string.h>
00030 #include <sys/mman.h>
00031 #include <sys/time.h>
00032 #include <sys/wait.h>
00033 #include <time.h>
00034 #include <unistd.h>
00035 #include "tst-mqueue.h"
00036 
00037 #if _POSIX_THREADS
00038 # include <pthread.h>
00039 
00040 # define mqsend(q) (mqsend) (q, __LINE__)
00041 static int
00042 (mqsend) (mqd_t q, int line)
00043 {
00044   char c;
00045   if (mq_send (q, &c, 1, 1) != 0)
00046     {
00047       printf ("mq_send on line %d failed with: %m\n", line);
00048       return 1;
00049     }
00050   return 0;
00051 }
00052 
00053 # define mqrecv(q) (mqrecv) (q, __LINE__)
00054 static int
00055 (mqrecv) (mqd_t q, int line)
00056 {
00057   char c;
00058   ssize_t rets = TEMP_FAILURE_RETRY (mq_receive (q, &c, 1, NULL));
00059   if (rets != 1)
00060     {
00061       if (rets == -1)
00062        printf ("mq_receive on line %d failed with: %m\n", line);
00063       else
00064        printf ("mq_receive on line %d returned %zd != 1\n",
00065               line, rets);
00066       return 1;
00067     }
00068   return 0;
00069 }
00070 
00071 volatile int fct_cnt, fct_err;
00072 size_t fct_guardsize;
00073 
00074 static void
00075 fct (union sigval s)
00076 {
00077   mqd_t q = *(mqd_t *) s.sival_ptr;
00078 
00079   pthread_attr_t nattr;
00080   int ret = pthread_getattr_np (pthread_self (), &nattr);
00081   if (ret)
00082     {
00083       errno = ret;
00084       printf ("pthread_getattr_np failed: %m\n");
00085       fct_err = 1;
00086     }
00087   else
00088     {
00089       ret = pthread_attr_getguardsize (&nattr, &fct_guardsize);
00090       if (ret)
00091        {
00092          errno = ret;
00093          printf ("pthread_attr_getguardsize failed: %m\n");
00094          fct_err = 1;
00095        }
00096       if (pthread_attr_destroy (&nattr) != 0)
00097        {
00098          puts ("pthread_attr_destroy failed");
00099          fct_err = 1;
00100        }
00101     }
00102 
00103   ++fct_cnt;
00104   fct_err |= mqsend (q);
00105 }
00106 
00107 # define TEST_FUNCTION do_test ()
00108 static int
00109 do_test (void)
00110 {
00111   int result = 0;
00112 
00113   char name[sizeof "/tst-mqueue6-" + sizeof (pid_t) * 3];
00114   snprintf (name, sizeof (name), "/tst-mqueue6-%u", getpid ());
00115 
00116   struct mq_attr attr = { .mq_maxmsg = 1, .mq_msgsize = 1 };
00117   mqd_t q = mq_open (name, O_CREAT | O_EXCL | O_RDWR, 0600, &attr);
00118 
00119   if (q == (mqd_t) -1)
00120     {
00121       printf ("mq_open failed with: %m\n");
00122       return result;
00123     }
00124   else
00125     add_temp_mq (name);
00126 
00127   pthread_attr_t nattr;
00128   if (pthread_attr_init (&nattr)
00129       || pthread_attr_setguardsize (&nattr, 0))
00130     {
00131       puts ("pthread_attr_t setup failed");
00132       result = 1;
00133     }
00134 
00135   fct_guardsize = 1;
00136 
00137   struct sigevent ev;
00138   memset (&ev, 0xaa, sizeof (ev));
00139   ev.sigev_notify = SIGEV_THREAD;
00140   ev.sigev_notify_function = fct;
00141   ev.sigev_notify_attributes = &nattr;
00142   ev.sigev_value.sival_ptr = &q;
00143   if (mq_notify (q, &ev) != 0)
00144     {
00145       printf ("mq_notify (q, { SIGEV_THREAD }) failed with: %m\n");
00146       result = 1;
00147     }
00148 
00149   size_t ps = sysconf (_SC_PAGESIZE);
00150   if (pthread_attr_setguardsize (&nattr, 32 * ps))
00151     {
00152       puts ("pthread_attr_t setup failed");
00153       result = 1;
00154     }
00155 
00156   if (mq_notify (q, &ev) == 0)
00157     {
00158       puts ("second mq_notify (q, { SIGEV_NONE }) unexpectedly succeeded");
00159       result = 1;
00160     }
00161   else if (errno != EBUSY)
00162     {
00163       printf ("second mq_notify (q, { SIGEV_NONE }) failed with: %m\n");
00164       result = 1;
00165     }
00166 
00167   if (fct_cnt != 0)
00168     {
00169       printf ("fct called too early (%d on %d)\n", fct_cnt, __LINE__);
00170       result = 1;
00171     }
00172 
00173   result |= mqsend (q);
00174 
00175   result |= mqrecv (q);
00176   result |= mqrecv (q);
00177 
00178   if (fct_cnt != 1)
00179     {
00180       printf ("fct not called (%d on %d)\n", fct_cnt, __LINE__);
00181       result = 1;
00182     }
00183   else if (fct_guardsize != 0)
00184     {
00185       printf ("fct_guardsize %zd != 0\n", fct_guardsize);
00186       result = 1;
00187     }
00188 
00189   if (mq_notify (q, &ev) != 0)
00190     {
00191       printf ("third mq_notify (q, { SIGEV_NONE }) failed with: %m\n");
00192       result = 1;
00193     }
00194 
00195   if (mq_notify (q, NULL) != 0)
00196     {
00197       printf ("mq_notify (q, NULL) failed with: %m\n");
00198       result = 1;
00199     }
00200 
00201   memset (&ev, 0x11, sizeof (ev));
00202   ev.sigev_notify = SIGEV_THREAD;
00203   ev.sigev_notify_function = fct;
00204   ev.sigev_notify_attributes = &nattr;
00205   ev.sigev_value.sival_ptr = &q;
00206   if (mq_notify (q, &ev) != 0)
00207     {
00208       printf ("mq_notify (q, { SIGEV_THREAD }) failed with: %m\n");
00209       result = 1;
00210     }
00211 
00212   if (pthread_attr_setguardsize (&nattr, 0))
00213     {
00214       puts ("pthread_attr_t setup failed");
00215       result = 1;
00216     }
00217 
00218   if (mq_notify (q, &ev) == 0)
00219     {
00220       puts ("second mq_notify (q, { SIGEV_NONE }) unexpectedly succeeded");
00221       result = 1;
00222     }
00223   else if (errno != EBUSY)
00224     {
00225       printf ("second mq_notify (q, { SIGEV_NONE }) failed with: %m\n");
00226       result = 1;
00227     }
00228 
00229   if (fct_cnt != 1)
00230     {
00231       printf ("fct called too early (%d on %d)\n", fct_cnt, __LINE__);
00232       result = 1;
00233     }
00234 
00235   result |= mqsend (q);
00236 
00237   result |= mqrecv (q);
00238   result |= mqrecv (q);
00239 
00240   if (fct_cnt != 2)
00241     {
00242       printf ("fct not called (%d on %d)\n", fct_cnt, __LINE__);
00243       result = 1;
00244     }
00245   else if (fct_guardsize != 32 * ps)
00246     {
00247       printf ("fct_guardsize %zd != %zd\n", fct_guardsize, 32 * ps);
00248       result = 1;
00249     }
00250 
00251   if (mq_notify (q, &ev) != 0)
00252     {
00253       printf ("third mq_notify (q, { SIGEV_NONE }) failed with: %m\n");
00254       result = 1;
00255     }
00256 
00257   if (mq_notify (q, NULL) != 0)
00258     {
00259       printf ("mq_notify (q, NULL) failed with: %m\n");
00260       result = 1;
00261     }
00262 
00263   if (pthread_attr_destroy (&nattr) != 0)
00264     {
00265       puts ("pthread_attr_destroy failed");
00266       result = 1;
00267     }
00268 
00269   if (mq_unlink (name) != 0)
00270     {
00271       printf ("mq_unlink failed: %m\n");
00272       result = 1;
00273     }
00274 
00275   if (mq_close (q) != 0)
00276     {
00277       printf ("mq_close failed: %m\n");
00278       result = 1;
00279     }
00280 
00281   memset (&ev, 0x55, sizeof (ev));
00282   ev.sigev_notify = SIGEV_THREAD;
00283   ev.sigev_notify_function = fct;
00284   ev.sigev_notify_attributes = NULL;
00285   ev.sigev_value.sival_int = 0;
00286   if (mq_notify (q, &ev) == 0)
00287     {
00288       puts ("mq_notify on closed mqd_t unexpectedly succeeded");
00289       result = 1;
00290     }
00291   else if (errno != EBADF)
00292     {
00293       printf ("mq_notify on closed mqd_t did not fail with EBADF: %m\n");
00294       result = 1;
00295     }
00296 
00297   if (fct_err)
00298     result = 1;
00299   return result;
00300 }
00301 #else
00302 # define TEST_FUNCTION 0
00303 #endif
00304 
00305 #include "../test-skeleton.c"