(root)/
glibc-2.38/
nptl/
tst-cancel4_2.c
       1  /* Check recvmmsg cancellation.
       2  
       3     Copyright (C) 2016-2023 Free Software Foundation, Inc.
       4     This file is part of the GNU C Library.
       5  
       6     The GNU C Library is free software; you can redistribute it and/or
       7     modify it under the terms of the GNU Lesser General Public
       8     License as published by the Free Software Foundation; either
       9     version 2.1 of the License, or (at your option) any later version.
      10  
      11     The GNU C Library is distributed in the hope that it will be useful,
      12     but WITHOUT ANY WARRANTY; without even the implied warranty of
      13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14     Lesser General Public License for more details.
      15  
      16     You should have received a copy of the GNU Lesser General Public
      17     License along with the GNU C Library; if not, see
      18     <https://www.gnu.org/licenses/>.  */
      19  
      20  #include <stdio.h>
      21  #include <stddef.h>
      22  #include <stdlib.h>
      23  #include <string.h>
      24  #include <sys/types.h>
      25  #include <sys/socket.h>
      26  #include <sys/un.h>
      27  #include <sys/ipc.h>
      28  #include <sys/msg.h>
      29  #include <unistd.h>
      30  #include <errno.h>
      31  #include <pthread.h>
      32  
      33  #include "tst-cancel4-common.h"
      34  
      35  static void *
      36  tf_recvmmsg (void *arg)
      37  {
      38    struct sockaddr_un sun;
      39  
      40    tempfd = socket (AF_UNIX, SOCK_DGRAM, 0);
      41    if (tempfd == -1)
      42      FAIL_EXIT1 ("socket (AF_UNIX, SOCK_DGRAM, 0): %m");
      43  
      44    int tries = 0;
      45    do
      46      {
      47        if (++tries > 10)
      48  	FAIL_EXIT1 ("too many unsuccessful bind calls");
      49  
      50        strcpy (sun.sun_path, "/tmp/tst-cancel4-socket-5-XXXXXX");
      51        if (mktemp (sun.sun_path) == NULL)
      52  	FAIL_EXIT1 ("cannot generate temp file name");
      53  
      54        sun.sun_family = AF_UNIX;
      55      }
      56    while (bind (tempfd, (struct sockaddr *) &sun,
      57  	       offsetof (struct sockaddr_un, sun_path)
      58  	       + strlen (sun.sun_path) + 1) != 0);
      59  
      60    tempfname = strdup (sun.sun_path);
      61  
      62    tempfd2 = socket (AF_UNIX, SOCK_DGRAM, 0);
      63    if (tempfd2 == -1)
      64      FAIL_EXIT1 ("socket (AF_UNIX, SOCK_DGRAM, 0): %m");
      65  
      66    int r = pthread_barrier_wait (&b2);
      67    if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
      68      FAIL_EXIT1 ("pthread_barrier_wait");
      69  
      70    if (arg != NULL)
      71      {
      72        r = pthread_barrier_wait (&b2);
      73        if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
      74  	FAIL_EXIT1 ("pthread_barrier_wait");
      75      }
      76  
      77    pthread_cleanup_push (cl, NULL);
      78  
      79    char mem[70];
      80    struct iovec iov[1];
      81    iov[0].iov_base = mem;
      82    iov[0].iov_len = arg == NULL ? sizeof (mem) : 0;
      83  
      84    struct mmsghdr mm;
      85    mm.msg_hdr.msg_name = &sun;
      86    mm.msg_hdr.msg_namelen = sizeof (sun);
      87    mm.msg_hdr.msg_iov = iov;
      88    mm.msg_hdr.msg_iovlen = 1;
      89    mm.msg_hdr.msg_control = NULL;
      90    mm.msg_hdr.msg_controllen = 0;
      91  
      92    ssize_t ret = recvmmsg (tempfd2, &mm, 1, 0, NULL);
      93    if (ret == -1 && errno == ENOSYS)
      94      exit (77);
      95  
      96    pthread_cleanup_pop (0);
      97  
      98    FAIL_EXIT1 ("recvmmsg returned");
      99  }
     100  
     101  struct cancel_tests tests[] =
     102  {
     103    ADD_TEST (recvmmsg, 2, 1),
     104  };
     105  #define ntest_tf (sizeof (tests) / sizeof (tests[0]))
     106  
     107  #include "tst-cancel4-common.c"