(root)/
glibc-2.38/
sysdeps/
pthread/
tst-sem4.c
       1  /* Copyright (C) 2002-2023 Free Software Foundation, Inc.
       2     This file is part of the GNU C Library.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public
       6     License as published by the Free Software Foundation; either
       7     version 2.1 of the License, or (at your option) any later version.
       8  
       9     The GNU C Library is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; if not, see
      16     <https://www.gnu.org/licenses/>.  */
      17  
      18  #include <errno.h>
      19  #include <fcntl.h>
      20  #include <semaphore.h>
      21  #include <stdio.h>
      22  #include <stdlib.h>
      23  #include <unistd.h>
      24  
      25  
      26  static void
      27  remove_sem (int status, void *arg)
      28  {
      29    sem_unlink (arg);
      30  }
      31  
      32  
      33  int
      34  do_test (void)
      35  {
      36    sem_t *s;
      37    sem_t *s2;
      38    pid_t pid;
      39    int val;
      40  
      41    /* Start with a clean slate and register a clean-up action.  No need to
      42       act if sem_unlink fails because we will catch the same problem during the
      43       sem_open below.  */
      44    sem_unlink ("/glibc-tst-sem4");
      45    on_exit (remove_sem, (void *) "/glibc-tst-sem4");
      46  
      47    s = sem_open ("/glibc-tst-sem4", O_CREAT, 0600, 1);
      48    if (s == SEM_FAILED)
      49      {
      50        if (errno == ENOSYS)
      51  	{
      52  	  puts ("sem_open not supported.  Oh well.");
      53  	  return 0;
      54  	}
      55  
      56        /* Maybe the shm filesystem has strict permissions.  */
      57        if (errno == EACCES)
      58  	{
      59  	  puts ("sem_open not allowed.  Oh well.");
      60  	  return 0;
      61  	}
      62  
      63        printf ("sem_open: %m\n");
      64        return 1;
      65      }
      66  
      67    /* We have the semaphore object.  Now try again with O_EXCL, this
      68       should fail.  */
      69    s2 = sem_open ("/glibc-tst-sem4", O_CREAT | O_EXCL, 0600, 1);
      70    if (s2 != SEM_FAILED)
      71      {
      72        puts ("2nd sem_open didn't fail");
      73        return 1;
      74      }
      75    if (errno != EEXIST)
      76      {
      77        puts ("2nd sem_open returned wrong error");
      78        return 1;
      79      }
      80  
      81    /* Check the value.  */
      82    if (sem_getvalue (s, &val) == -1)
      83      {
      84        puts ("getvalue failed");
      85        return 1;
      86      }
      87    if (val != 1)
      88      {
      89        printf ("initial value wrong: got %d, expected 1\n", val);
      90        return 1;
      91      }
      92  
      93    if (TEMP_FAILURE_RETRY (sem_wait (s)) == -1)
      94      {
      95        puts ("1st sem_wait failed");
      96        return 1;
      97      }
      98  
      99    pid = fork ();
     100    if (pid == -1)
     101      {
     102        printf ("fork failed: %m\n");
     103        return 1;
     104      }
     105  
     106    if (pid == 0)
     107      {
     108        /* Child.  */
     109  
     110        /* Check the value.  */
     111        if (sem_getvalue (s, &val) == -1)
     112  	{
     113  	  puts ("child: getvalue failed");
     114  	  return 1;
     115  	}
     116        if (val != 0)
     117  	{
     118  	  printf ("child: value wrong: got %d, expect 0\n", val);
     119  	  return 1;
     120  	}
     121  
     122        if (sem_post (s) == -1)
     123  	{
     124  	  puts ("child: post failed");
     125  	  return 1;
     126  	}
     127      }
     128    else
     129      {
     130        if (TEMP_FAILURE_RETRY (sem_wait (s)) == -1)
     131  	{
     132  	  puts ("2nd sem_wait failed");
     133  	  return 1;
     134  	}
     135  
     136        if (sem_getvalue (s, &val) == -1)
     137  	{
     138  	  puts ("parent: 2nd getvalue failed");
     139  	  return 1;
     140  	}
     141        if (val != 0)
     142  	{
     143  	  printf ("parent: value wrong: got %d, expected 0\n", val);
     144  	  return 1;
     145  	}
     146      }
     147  
     148    return 0;
     149  }
     150  
     151  #define TEST_FUNCTION do_test ()
     152  #include "../test-skeleton.c"