(root)/
glibc-2.38/
rt/
tst-mqueue2.c
       1  /* Test message queue passing.
       2     Copyright (C) 2004-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <errno.h>
      20  #include <fcntl.h>
      21  #include <mqueue.h>
      22  #include <signal.h>
      23  #include <stdio.h>
      24  #include <stdlib.h>
      25  #include <string.h>
      26  #include <sys/time.h>
      27  #include <sys/wait.h>
      28  #include <time.h>
      29  #include <unistd.h>
      30  #include <support/check.h>
      31  #include "tst-mqueue.h"
      32  
      33  static void
      34  alrm_handler (int sig)
      35  {
      36  }
      37  
      38  #define TEST_FUNCTION do_test ()
      39  static int
      40  do_test (void)
      41  {
      42    int result = 0;
      43  
      44    char name[sizeof "/tst-mqueue2-" + sizeof (pid_t) * 3];
      45    snprintf (name, sizeof (name), "/tst-mqueue2-%u", getpid ());
      46  
      47    struct mq_attr attr = { .mq_maxmsg = 2, .mq_msgsize = 2 };
      48    mqd_t q = mq_open (name, O_CREAT | O_EXCL | O_RDWR, 0600, &attr);
      49  
      50    if (q == (mqd_t) -1)
      51      {
      52        if (errno == ENOSYS)
      53  	FAIL_UNSUPPORTED ("mq_open not supported");
      54  
      55        printf ("mq_open failed with: %m\n");
      56        return 1;
      57      }
      58  
      59    add_temp_mq (name);
      60  
      61    mqd_t q2 = mq_open (name, O_CREAT | O_EXCL | O_RDWR, 0600, &attr);
      62    if (q2 != (mqd_t) -1)
      63      {
      64        puts ("mq_open with O_EXCL unexpectedly succeeded");
      65        result = 1;
      66      }
      67    else if (errno != EEXIST)
      68      {
      69        printf ("mq_open did not fail with EEXIST: %m\n");
      70        result = 1;
      71      }
      72  
      73    char name2[sizeof "/tst-mqueue2-2-" + sizeof (pid_t) * 3];
      74    snprintf (name2, sizeof (name2), "/tst-mqueue2-2-%u", getpid ());
      75  
      76    attr.mq_maxmsg = -2;
      77    q2 = mq_open (name2, O_CREAT | O_EXCL | O_RDWR, 0600, &attr);
      78    if (q2 != (mqd_t) -1)
      79      {
      80        puts ("mq_open with invalid mq_maxmsg unexpectedly succeeded");
      81        add_temp_mq (name2);
      82        result = 1;
      83      }
      84    else if (errno != EINVAL)
      85      {
      86        printf ("mq_open with invalid mq_maxmsg did not fail with "
      87  	      "EINVAL: %m\n");
      88        result = 1;
      89      }
      90  
      91    attr.mq_maxmsg = 2;
      92    attr.mq_msgsize = -56;
      93    q2 = mq_open (name2, O_CREAT | O_EXCL | O_RDWR, 0600, &attr);
      94    if (q2 != (mqd_t) -1)
      95      {
      96        puts ("mq_open with invalid mq_msgsize unexpectedly succeeded");
      97        add_temp_mq (name2);
      98        result = 1;
      99      }
     100    else if (errno != EINVAL)
     101      {
     102        printf ("mq_open with invalid mq_msgsize did not fail with "
     103  	      "EINVAL: %m\n");
     104        result = 1;
     105      }
     106  
     107    char buf[3];
     108    struct timespec ts;
     109    if (clock_gettime (CLOCK_REALTIME, &ts) == 0)
     110      ts.tv_sec += 10;
     111    else
     112      {
     113        ts.tv_sec = time (NULL) + 10;
     114        ts.tv_nsec = 0;
     115      }
     116  
     117    if (mq_timedreceive (q, buf, 1, NULL, &ts) == 0)
     118      {
     119        puts ("mq_timedreceive with too small msg_len did not fail");
     120        result = 1;
     121      }
     122    else if (errno != EMSGSIZE)
     123      {
     124        printf ("mq_timedreceive with too small msg_len did not fail with "
     125  	      "EMSGSIZE: %m\n");
     126        result = 1;
     127      }
     128  
     129    ts.tv_nsec = -1;
     130    if (mq_timedreceive (q, buf, 2, NULL, &ts) == 0)
     131      {
     132        puts ("mq_timedreceive with negative tv_nsec did not fail");
     133        result = 1;
     134      }
     135    else if (errno != EINVAL)
     136      {
     137        printf ("mq_timedreceive with negative tv_nsec did not fail with "
     138  	      "EINVAL: %m\n");
     139        result = 1;
     140      }
     141  
     142    ts.tv_nsec = 1000000000;
     143    if (mq_timedreceive (q, buf, 2, NULL, &ts) == 0)
     144      {
     145        puts ("mq_timedreceive with tv_nsec >= 1000000000 did not fail");
     146        result = 1;
     147      }
     148    else if (errno != EINVAL)
     149      {
     150        printf ("mq_timedreceive with tv_nsec >= 1000000000 did not fail with "
     151  	      "EINVAL: %m\n");
     152        result = 1;
     153      }
     154  
     155    struct sigaction sa = { .sa_handler = alrm_handler, .sa_flags = 0 };
     156    sigemptyset (&sa.sa_mask);
     157    sigaction (SIGALRM, &sa, NULL);
     158  
     159    struct itimerval it = { .it_value = { .tv_sec = 1 } };
     160    setitimer (ITIMER_REAL, &it, NULL);
     161  
     162    if (mq_receive (q, buf, 2, NULL) == 0)
     163      {
     164        puts ("mq_receive on empty queue did not block");
     165        result = 1;
     166      }
     167    else if (errno != EINTR)
     168      {
     169        printf ("mq_receive on empty queue did not fail with EINTR: %m\n");
     170        result = 1;
     171      }
     172  
     173    setitimer (ITIMER_REAL, &it, NULL);
     174  
     175    ts.tv_nsec = 0;
     176    if (mq_timedreceive (q, buf, 2, NULL, &ts) == 0)
     177      {
     178        puts ("mq_timedreceive on empty queue did not block");
     179        result = 1;
     180      }
     181    else if (errno != EINTR)
     182      {
     183        printf ("mq_timedreceive on empty queue did not fail with EINTR: %m\n");
     184        result = 1;
     185      }
     186  
     187    buf[0] = '6';
     188    buf[1] = '7';
     189    if (mq_send (q, buf, 2, 3) != 0
     190        || (buf[0] = '8', mq_send (q, buf, 1, 4) != 0))
     191      {
     192        printf ("mq_send failed: %m\n");
     193        result = 1;
     194      }
     195  
     196    memset (buf, ' ', sizeof (buf));
     197  
     198    unsigned int prio;
     199    ssize_t rets = mq_receive (q, buf, 3, &prio);
     200    if (rets != 1)
     201      {
     202        if (rets == -1)
     203  	printf ("mq_receive failed: %m\n");
     204        else
     205  	printf ("mq_receive returned %zd != 1\n", rets);
     206        result = 1;
     207      }
     208    else if (prio != 4 || memcmp (buf, "8  ", 3) != 0)
     209      {
     210        printf ("mq_receive prio %u (4) buf \"%c%c%c\" (\"8  \")\n",
     211  	      prio, buf[0], buf[1], buf[2]);
     212        result = 1;
     213      }
     214  
     215    rets = mq_receive (q, buf, 2, NULL);
     216    if (rets != 2)
     217      {
     218        if (rets == -1)
     219  	printf ("mq_receive failed: %m\n");
     220        else
     221  	printf ("mq_receive returned %zd != 2\n", rets);
     222        result = 1;
     223      }
     224    else if (memcmp (buf, "67 ", 3) != 0)
     225      {
     226        printf ("mq_receive buf \"%c%c%c\" != \"67 \"\n",
     227  	      buf[0], buf[1], buf[2]);
     228        result = 1;
     229      }
     230  
     231    buf[0] = '2';
     232    buf[1] = '1';
     233    if (clock_gettime (CLOCK_REALTIME, &ts) != 0)
     234      ts.tv_sec = time (NULL);
     235    ts.tv_nsec = -1000000001;
     236    if ((mq_timedsend (q, buf, 2, 5, &ts) != 0
     237         && (errno != EINVAL || mq_send (q, buf, 2, 5) != 0))
     238        || (buf[0] = '3', ts.tv_nsec = -ts.tv_nsec,
     239  	  (mq_timedsend (q, buf, 1, 4, &ts) != 0
     240  	   && (errno != EINVAL || mq_send (q, buf, 1, 4) != 0))))
     241      {
     242        printf ("mq_timedsend failed: %m\n");
     243        result = 1;
     244      }
     245  
     246    buf[0] = '-';
     247    ts.tv_nsec = 1000000001;
     248    if (mq_timedsend (q, buf, 1, 6, &ts) == 0)
     249      {
     250        puts ("mq_timedsend with tv_nsec >= 1000000000 did not fail");
     251        result = 1;
     252      }
     253    else if (errno != EINVAL)
     254      {
     255        printf ("mq_timedsend with tv_nsec >= 1000000000 did not fail with "
     256  	      "EINVAL: %m\n");
     257        result = 1;
     258      }
     259  
     260    ts.tv_nsec = -2;
     261    if (mq_timedsend (q, buf, 1, 6, &ts) == 0)
     262      {
     263        puts ("mq_timedsend with negative tv_nsec did not fail");
     264        result = 1;
     265      }
     266    else if (errno != EINVAL)
     267      {
     268        printf ("mq_timedsend with megatove tv_nsec did not fail with "
     269  	      "EINVAL: %m\n");
     270        result = 1;
     271      }
     272  
     273    setitimer (ITIMER_REAL, &it, NULL);
     274  
     275    if (mq_send (q, buf, 2, 8) == 0)
     276      {
     277        puts ("mq_send on full queue did not block");
     278        result = 1;
     279      }
     280    else if (errno != EINTR)
     281      {
     282        printf ("mq_send on full queue did not fail with EINTR: %m\n");
     283        result = 1;
     284      }
     285  
     286    setitimer (ITIMER_REAL, &it, NULL);
     287  
     288    ts.tv_sec += 10;
     289    ts.tv_nsec = 0;
     290    if (mq_timedsend (q, buf, 2, 7, &ts) == 0)
     291      {
     292        puts ("mq_timedsend on full queue did not block");
     293        result = 1;
     294      }
     295    else if (errno != EINTR)
     296      {
     297        printf ("mq_timedsend on full queue did not fail with EINTR: %m\n");
     298        result = 1;
     299      }
     300  
     301    memset (buf, ' ', sizeof (buf));
     302  
     303    if (clock_gettime (CLOCK_REALTIME, &ts) != 0)
     304      ts.tv_sec = time (NULL);
     305    ts.tv_nsec = -1000000001;
     306    rets = mq_timedreceive (q, buf, 2, &prio, &ts);
     307    if (rets == -1 && errno == EINVAL)
     308      rets = mq_receive (q, buf, 2, &prio);
     309    if (rets != 2)
     310      {
     311        if (rets == -1)
     312  	printf ("mq_timedreceive failed: %m\n");
     313        else
     314  	printf ("mq_timedreceive returned %zd != 2\n", rets);
     315        result = 1;
     316      }
     317    else if (prio != 5 || memcmp (buf, "21 ", 3) != 0)
     318      {
     319        printf ("mq_timedreceive prio %u (5) buf \"%c%c%c\" (\"21 \")\n",
     320  	      prio, buf[0], buf[1], buf[2]);
     321        result = 1;
     322      }
     323  
     324    if (mq_receive (q, buf, 1, NULL) == 0)
     325      {
     326        puts ("mq_receive with too small msg_len did not fail");
     327        result = 1;
     328      }
     329    else if (errno != EMSGSIZE)
     330      {
     331        printf ("mq_receive with too small msg_len did not fail with "
     332  	      "EMSGSIZE: %m\n");
     333        result = 1;
     334      }
     335  
     336    ts.tv_nsec = -ts.tv_nsec;
     337    rets = mq_timedreceive (q, buf, 2, NULL, &ts);
     338    if (rets == -1 && errno == EINVAL)
     339      rets = mq_receive (q, buf, 2, NULL);
     340    if (rets != 1)
     341      {
     342        if (rets == -1)
     343  	printf ("mq_timedreceive failed: %m\n");
     344        else
     345  	printf ("mq_timedreceive returned %zd != 1\n", rets);
     346        result = 1;
     347      }
     348    else if (memcmp (buf, "31 ", 3) != 0)
     349      {
     350        printf ("mq_timedreceive buf \"%c%c%c\" != \"31 \"\n",
     351  	      buf[0], buf[1], buf[2]);
     352        result = 1;
     353      }
     354  
     355    if (mq_send (q, "", 0, 2) != 0)
     356      {
     357        printf ("mq_send with msg_len 0 failed: %m\n");
     358        result = 1;
     359      }
     360  
     361    rets = mq_receive (q, buf, 2, &prio);
     362    if (rets)
     363      {
     364        if (rets == -1)
     365  	printf ("mq_receive failed: %m\n");
     366        else
     367  	printf ("mq_receive returned %zd != 0\n", rets);
     368        result = 1;
     369      }
     370  
     371    long mq_prio_max = sysconf (_SC_MQ_PRIO_MAX);
     372    if (mq_prio_max > 0 && (unsigned int) mq_prio_max == mq_prio_max)
     373      {
     374        if (mq_send (q, buf, 1, mq_prio_max) == 0)
     375  	{
     376  	  puts ("mq_send with MQ_PRIO_MAX priority unpexpectedly succeeded");
     377  	  result = 1;
     378  	}
     379        else if (errno != EINVAL)
     380  	{
     381  	  printf ("mq_send with MQ_PRIO_MAX priority did not fail with "
     382  		  "EINVAL: %m\n");
     383  	  result = 1;
     384  	}
     385  
     386        if (mq_send (q, buf, 1, mq_prio_max - 1) != 0)
     387  	{
     388  	  printf ("mq_send with MQ_PRIO_MAX-1 priority failed: %m\n");
     389  	  result = 1;
     390  	}
     391      }
     392  
     393    if (mq_unlink (name) != 0)
     394      {
     395        printf ("mq_unlink failed: %m\n");
     396        result = 1;
     397      }
     398  
     399    q2 = mq_open (name, O_RDWR);
     400    if (q2 != (mqd_t) -1)
     401      {
     402        printf ("mq_open of unlinked %s without O_CREAT unexpectedly"
     403  	      "succeeded\n", name);
     404        result = 1;
     405      }
     406    else if (errno != ENOENT)
     407      {
     408        printf ("mq_open of unlinked %s without O_CREAT did not fail with "
     409  	      "ENOENT: %m\n", name);
     410        result = 1;
     411      }
     412  
     413    if (mq_close (q) != 0)
     414      {
     415        printf ("mq_close in parent failed: %m\n");
     416        result = 1;
     417      }
     418  
     419    if (mq_receive (q, buf, 2, NULL) == 0)
     420      {
     421        puts ("mq_receive on invalid mqd_t did not fail");
     422        result = 1;
     423      }
     424    else if (errno != EBADF)
     425      {
     426        printf ("mq_receive on invalid mqd_t did not fail with EBADF: %m\n");
     427        result = 1;
     428      }
     429  
     430    if (mq_send (q, buf, 1, 2) == 0)
     431      {
     432        puts ("mq_send on invalid mqd_t did not fail");
     433        result = 1;
     434      }
     435    else if (errno != EBADF)
     436      {
     437        printf ("mq_send on invalid mqd_t did not fail with EBADF: %m\n");
     438        result = 1;
     439      }
     440  
     441    if (mq_getattr (q, &attr) == 0)
     442      {
     443        puts ("mq_getattr on invalid mqd_t did not fail");
     444        result = 1;
     445      }
     446    else if (errno != EBADF)
     447      {
     448        printf ("mq_getattr on invalid mqd_t did not fail with EBADF: %m\n");
     449        result = 1;
     450      }
     451  
     452    memset (&attr, 0, sizeof (attr));
     453    if (mq_setattr (q, &attr, NULL) == 0)
     454      {
     455        puts ("mq_setattr on invalid mqd_t did not fail");
     456        result = 1;
     457      }
     458    else if (errno != EBADF)
     459      {
     460        printf ("mq_setattr on invalid mqd_t did not fail with EBADF: %m\n");
     461        result = 1;
     462      }
     463  
     464    if (mq_unlink ("/tst-mqueue2-which-should-never-exist") != -1)
     465      {
     466        puts ("mq_unlink of non-existent message queue unexpectedly succeeded");
     467        result = 1;
     468      }
     469    else if (errno != ENOENT)
     470      {
     471        printf ("mq_unlink of non-existent message queue did not fail with "
     472  	      "ENOENT: %m\n");
     473        result = 1;
     474      }
     475    return result;
     476  }
     477  
     478  #include "../test-skeleton.c"